package com.shop2cn.iapi.shenqisettlement.verify;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.shop2cn.iapi.accounting.parameter.AccountTypeEnum;
import org.apache.http.client.ClientProtocolException;

import com.shop2cn.iapi.shenqisettlement.parameter.OnHpSettledReq;
import com.shop2cn.iapi.shenqisettlement.parameter.bean.AgentPromoterProductBean;
import com.shop2cn.iapi.shenqisettlement.parameter.bean.AgentPromoterRelationSettlementBean;
import com.shop2cn.iapi.shenqisettlement.parameter.bean.IndependentMerchantInfoBean;
import com.shop2cn.iapi.shenqisettlement.parameter.bean.ProviderBean;
import com.shop2cn.iapi.sqoptrade.parameter.utill.Utils;
import com.shop2cn.iapi.agentproducts.parameter.ProductDetailsDto;
import com.ymatou.iapi.godmch.parameter.MchInfoVo;
import com.ymatou.iapi.godmch.parameter.MerchantFundCollectConfigResp;
import com.ymatou.iapi.synctrade.parameter.mongo.ProxyIndex;
import com.ymatou.iapi.synctrade.service.TradingSyncService;
import com.ymt.core.tool.Logger;
import com.ymttest.business.service.SQPayGateWayCallService;
import com.ymttest.business.service.shenqi.DGSQBaseService;
import com.ymttest.business.service.shenqi.GodmchManageCallService;
import com.ymttest.business.service.shenqi.ProxyFissionVerifyService;
import com.ymttest.business.service.shenqi.RefundService;
import com.ymttest.business.service.shenqi.ShenqiSettlementService;
import com.ymttest.business.service.shenqi.SqTradingCallService;
import com.ymttest.business.service.shenqi.SqTradingProductService;
import com.ymttest.database.model.AccountEntry;
import com.ymttest.database.model.shenqi.SqliveOrderDetail;
import com.ymttest.database.model.shenqisettlement.CurrencyConfig;
import com.ymttest.database.model.shenqisettlement.GoodsOwnerSettlementConfig;
import com.ymttest.database.model.shenqisettlement.MchFeeConfig;
import com.ymttest.database.model.shenqisettlement.OrderSettlement;
import com.ymttest.database.model.shenqisettlement.OrderSettlementDetail;
import com.ymttest.database.model.shenqisettlement.PlatformProductDetail;
import com.ymttest.database.model.shenqisettlement.ProviderSettlementDetail;
import com.ymttest.database.model.shenqisettlement.ProxyFissionConfig;
import com.ymttest.database.sharding.db.ext.model.OrderExtPo;
import com.ymttest.database.sharding.db.sharding.model.OrderDetailPo;
import com.ymttest.database.sharding.db.sharding.model.OrderPo;
import com.ymttest.database.sharding.db.sharding.model.PaymentDetailPo;
import com.ymttest.database.sharding.db.sharding.model.PaymentPo;
import com.ymttest.database.sharding.db.sharding.model.RefundBillPo;
import com.ymttest.database.sharding.db.sharding.model.ShenqiProxyChainPo;
import com.ymttest.database.sharding.db.sqlwapper.OrderShardingWapper;
import com.ymttest.database.sharding.db.sqlwapper.OrderWapper;
import com.ymttest.database.sqlwapper.AccountWapper;
import com.ymttest.database.sqlwapper.shenqi.SqliveOrderDetailWrapper;
import com.ymttest.database.sqlwapper.shenqisettlement.CurrencyConfigWrapper;
import com.ymttest.database.sqlwapper.shenqisettlement.GoodsOwnerSettlementConfigWrapper;
import com.ymttest.database.sqlwapper.shenqisettlement.MchFeeConfigWrapper;
import com.ymttest.database.sqlwapper.shenqisettlement.OrderSettlementDetailWrapper;
import com.ymttest.database.sqlwapper.shenqisettlement.OrderSettlementWrapper;
import com.ymttest.database.sqlwapper.shenqisettlement.PlatformProductDetailWrapper;
import com.ymttest.database.sqlwapper.shenqisettlement.ProviderSettlementDetailWrapper;
import com.ymttest.database.sqlwapper.shenqisettlement.ProxyFissionConfigWrapper;
import com.ymttest.utils.DataUtil;
import com.ymttest.utils.YMTDateUtil;

public class ShenqiSettlementBuildVerifyService {

	private static SqliveOrderDetailWrapper sqliveOrderDetailWrapper = new SqliveOrderDetailWrapper();
	private static ProxyFissionConfigWrapper proxyFissionConfigWrapper = new ProxyFissionConfigWrapper();

	// 代购神器测试固定汇率
	private static String settleHKRate = SQPayGateWayCallService.HKExchangeRate;

	private static OrderSettlementDetailWrapper orderSettlementDetailWrapper = new OrderSettlementDetailWrapper();
	private static OrderSettlementWrapper orderSettlementWrapper = new OrderSettlementWrapper();
	private static ProviderSettlementDetailWrapper providerSettlementDetailWrapper = new ProviderSettlementDetailWrapper();

	private static OrderShardingWapper wapper = new OrderShardingWapper();
	private static OrderWapper orderWapper = new OrderWapper();

	private static MchFeeConfigWrapper mchFeeConfigWrapper = new MchFeeConfigWrapper();
	private static GoodsOwnerSettlementConfigWrapper goodsOwnerSettlementConfigWrapper = new GoodsOwnerSettlementConfigWrapper();

	/**
	 * 返回软件服务商固定配置费率
	 * 
	 * @param isDirect
	 * @return
	 */
	private BigDecimal getProviderPlatformFeeRate(boolean isDirect) {

		if (isDirect)
			return new BigDecimal("1.00");
		else
			return new BigDecimal("1.30");
	}

	// new
	private HashMap<String, Object> isDependentOrderNew(
			List<ShenqiProxyChainPo> chainPoList,
			HashMap<String, Object> independentOrderRelationHashMap)
			throws ClientProtocolException, IOException {

		ArrayList<IndependentMerchantInfoBean> independentMerchantInfos = new ArrayList<>();

		Boolean isIndependentOrder = false;

		for (ShenqiProxyChainPo po : chainPoList) {

			MchInfoVo mchInfoVo = GodmchManageCallService
					.getMchInfoBySellerId(po.getSellerId());

			int mchType = mchInfoVo.getMchType();

			Boolean indepMchSelf = mchInfoVo.getIndepMchSelf();
			
			// 如果是独立商户
			if (mchType == 2)
				isIndependentOrder = true;

			// 如果是独立主商户
			if (mchType == 2 && indepMchSelf) {

				IndependentMerchantInfoBean independentMerchantInfo = new IndependentMerchantInfoBean();

				independentMerchantInfo.setMchInfoVo(mchInfoVo);

				independentMerchantInfos.add(independentMerchantInfo);
			}
		}

		independentOrderRelationHashMap.put("isIndependentOrder",
				isIndependentOrder);
		independentOrderRelationHashMap.put("independentMerchantInfos",
				independentMerchantInfos);

		return independentOrderRelationHashMap;
	}

	public BigDecimal getWhitelistMerchantRateNew(int payChannelType,
			Long sellerId, boolean isDirect, boolean independentMerchant,
			int payMode, int orderType) {

		MchFeeConfig mchFeeConfig = null;

		HashMap<String, Object> map = new HashMap<>();

		map.put("pay_channel_type", payChannelType);
		map.put("pay_mode_type", payMode);
		map.put("mch_id", sellerId);

		map.put("fee_mch_type", "RATE_APPORTION");

		mchFeeConfig = mchFeeConfigWrapper.selectByHashMap(map);

		// 如果商家没有配置白名单
		if (null == mchFeeConfig) {

			return null;
		} else {

			if (orderType == 1)
				return mchFeeConfig.getDouyin_order_fee_rate();
			else if (orderType == 2)
				return mchFeeConfig.getLive_order_fee_rate();
			else {
				return mchFeeConfig.getFee_rate();
			}
		}
	}

	/**
	 * 新费率
	 * 
	 * @param payChannelType
	 * @param sellerId
	 * @param isDirect
	 * @param independentMerchant
	 * @param payMode
	 * @param orderType
	 * @return
	 */
	public BigDecimal getPlatformFeeRateNew(int payChannelType, Long sellerId,
			boolean isDirect, boolean independentMerchant,
			boolean isPlatformSupplier,
			ArrayList<PlatformProductDetail> platformProductDetailList,
			int payMode, int orderType) {

		MchFeeConfig mchFeeConfig = null;

		HashMap<String, Object> map = new HashMap<>();

		map.put("pay_channel_type", payChannelType);
		map.put("pay_mode_type", payMode);
		map.put("mch_id", sellerId);

		// 如果是微信直连，则rate为0
		if (payChannelType == 3 || payChannelType == 5)
			return BigDecimal.ZERO;

		if (independentMerchant) {

			map.put("fee_mch_type", "PRIVATE");

			mchFeeConfig = mchFeeConfigWrapper.selectByHashMap(map);

			// 如果独立商家没有配置单独的费率，则使用默认的费率
			if (null == mchFeeConfig) {
				map.put("mch_id", null);
				mchFeeConfig = mchFeeConfigWrapper.selectByHashMap(map);
			}

			if (orderType == 1)
				return mchFeeConfig.getDouyin_order_fee_rate();
			else if (orderType == 2)
				return mchFeeConfig.getLive_order_fee_rate();
			else
				return mchFeeConfig.getFee_rate();

		} else {

			map.put("fee_mch_type", "RATE_APPORTION");

			mchFeeConfig = mchFeeConfigWrapper.selectByHashMap(map);

			// 如果商家没有配置白名单
			if (null == mchFeeConfig) {

				if (isPlatformSupplier)
					map.put("fee_mch_type", "PLATFORM_SUPPLIER");
				else
					map.put("fee_mch_type", "PUBLIC");
				
				mchFeeConfig = mchFeeConfigWrapper.selectByHashMap(map);

				// 如果公共云商家没有配置单独的费率，则使用默认的费率
				if (null == mchFeeConfig) {
					map.put("mch_id", null);
					mchFeeConfig = mchFeeConfigWrapper.selectByHashMap(map);
				}
				
				if (orderType == 1)
					return mchFeeConfig.getDouyin_order_fee_rate();
				else if (orderType == 2)
					return mchFeeConfig.getLive_order_fee_rate();
				else if (isPlatformSupplier) {

					Long id = mchFeeConfig.getId();
					
					platformProductDetailList.forEach(detailPo -> {
						detailPo.setMch_fee_config_id(id);
					});

					return mchFeeConfig.getSupplier_rate();
				} else {
					
					if (isDirect)
						return mchFeeConfig.getFee_rate();
					else
						return mchFeeConfig.getProxy_order_fee_rate();
				}
			} else {

				if (orderType == 1)
					return mchFeeConfig.getDouyin_order_fee_rate();
				else if (orderType == 2)
					return mchFeeConfig.getLive_order_fee_rate();
				else {
					if (isDirect)
						return mchFeeConfig.getFee_rate();
					else
						return mchFeeConfig.getProxy_order_fee_rate();
				}
			}
		}
	}

	public int getScale(String currency) {

		// 根据币种类型，设置结算金额的保留小数位数
		CurrencyConfigWrapper currencyConfigWrapper = new CurrencyConfigWrapper();

		CurrencyConfig currencyConfig = currencyConfigWrapper
				.selectByPrimaryKey(currency);

		int scale = 0;

		scale = currencyConfig.getIs_support_decimal_places() ? 2 : 0;

		return scale;
	}

	public Boolean isAllRefunded(
			List<OrderSettlementDetail> orderSettlementDetailList, Long orderId) {

		// 结算单标价总金额
		BigDecimal totalSettlementDetailAmount = orderSettlementDetailList
				.stream()
				.filter(orderSettlementDetail -> orderSettlementDetail
						.getSettlement_type() == 0
						&& orderSettlementDetail.getSettlement_status() != -1)
				.map(OrderSettlementDetail::getTotal_rmb_amount)
				.reduce(BigDecimal.ZERO, BigDecimal::add);

		List<OrderSettlementDetail> refudedOrderSettlementDetailList = orderSettlementDetailWrapper
				.selectRefundedByOrderId(orderId);

		// 退款结算单标价总金额
		BigDecimal totalRefeundSettlementDetailAmount = refudedOrderSettlementDetailList
				.stream()
				.filter(orderSettlementDetail -> orderSettlementDetail
						.getSettlement_type() == 1
						&& orderSettlementDetail.getSettlement_status() != -1)
				.map(OrderSettlementDetail::getTotal_rmb_amount)
				.reduce(BigDecimal.ZERO, BigDecimal::add);

		if (totalRefeundSettlementDetailAmount.abs().compareTo(
				totalSettlementDetailAmount.abs()) == -1)
			return false;
		else
			return true;
	}

	public static int getAccountType(int payChannelType, String currency, boolean isFundCollectMerchant) {

		String accountTypeEnumName = "";
		
		if (payChannelType == 0)
			accountTypeEnumName = isFundCollectMerchant ? "GodMerchant"
					+ currency + "Account" : "GodMerchant" + currency
					+ "CollectAccount";
		else if (payChannelType == 1)
			accountTypeEnumName = "GodShengPayCNYAccount";
		else if (payChannelType == 62)
			accountTypeEnumName = "GodCMBDomesticCNYAccount";

		int accountType = AccountTypeEnum.getByName(accountTypeEnumName)
				.getCode();

		return accountType;
	}
	
	public static int getDistributorAccountType(int payChannelType, String currency, boolean isFundCollectMerchant) {

		String accountTypeEnumName = "";
		
		if (payChannelType == 0)
			accountTypeEnumName = isFundCollectMerchant ? "GodDistributorHipoPayCNYAccount"
					: "GodDistributorHipoPayCNYCollectAccount";
		else if (payChannelType == 1)
			accountTypeEnumName = "GodDistributorShengPayCNYAccount";
		else if (payChannelType == 62)
			accountTypeEnumName = "GodCMBDomesticCNYAccount";

		int accountType = AccountTypeEnum.getByName(accountTypeEnumName)
				.getCode();

		return accountType;
	}

	/**
	 * 获取orderType，先判断抖音订单，再判断直播订单，如果订单所有商品都在sqliveOrderDetail，就是直播订单
	 * 
	 * @param orderId
	 * @param orderDetailList
	 * @return
	 */
	private Integer getOrderType(Long orderId,
			List<OrderDetailPo> orderDetailList) {

		OrderExtPo orderExtPo = orderWapper.selectOrderExtByOrderId(orderId);

		if (orderExtPo.getSourcePlatform().equalsIgnoreCase("ShenqiDouyinMp"))
			return 1;
		else {

			List<SqliveOrderDetail> sqliveOrderDetailList = sqliveOrderDetailWrapper
					.selectByOrderId(orderId);

			if (sqliveOrderDetailList.size() == 0)
				return 0;

			for (OrderDetailPo orderDetailPo : orderDetailList) {

				SqliveOrderDetail sqliveOrderDetail = sqliveOrderDetailList
						.stream()
						.filter(detail -> detail.getCatalog_id()
								.equalsIgnoreCase(orderDetailPo.getCatalogId()))
						.findAny().orElse(null);

				if (null == sqliveOrderDetail)
					return 0;
			}

			return 2;
		}
	}

	public void verifySettlement(List<PaymentDetailPo> paymentDetails,
			boolean hpSettled, boolean settled, Boolean isForeignExchangeBid,
			Boolean isRefunded, Boolean isRefundedFailed,
			Boolean isCollectingForOthersSettled, OnHpSettledReq hpSettledReq)
			throws Exception {

		String settleRate = "";

		// 如果是外币结算，则结算汇率为1
		settleRate = isForeignExchangeBid ? "1" : settleHKRate;

		wapper.clearCache();

		long paymentId = paymentDetails.get(0).getPaymentId();
		PaymentPo paymentPo = wapper.selectPaymentById(paymentId);

		BigDecimal ymtSharingAmount = null;
		Boolean isShengPay = false;
		BigDecimal orderTotalPlatFormFee = BigDecimal.ZERO;
		Integer customSettlementCurrencyType = null;
		BigDecimal customer_payment_order_amount = paymentPo
				.getRealForeignAmount();
		
		String gatewayPayType = Utils
				.emptyIfNull(paymentPo.getGatewayPayType());

		Integer payMode = null;

		if (SqTradingCallService.isShengPay(paymentPo.getGatewayPayType()))
			isShengPay = true;
		else
			isShengPay = false;

		if (gatewayPayType.equalsIgnoreCase("6006")
				|| gatewayPayType.equalsIgnoreCase("6012"))
			payMode = 1;
		else
			payMode = 0;

		for (int i = 0; i < paymentDetails.size(); i++) {

			Boolean isAllRefunded = false;
			Boolean secondConfirmUnpaidOrder = false;

			PaymentDetailPo paymentDetailPo = paymentDetails.get(i);
			long orderId = paymentDetailPo.getOrderId();

			OrderPo order = wapper.selectOrderbyOrderId(orderId);
			
			Boolean freeOrderWithExchangeCoupon = order.getPayableAmount().compareTo(BigDecimal.ZERO) == 0
					&& order.getSellerCouponType() == 5;
			
			// 定金订单二次确认未支付且去掉订单
			if (Utils.zeroIfNull(order.getEarnestPaymentId()) != 0
					&& Utils.zeroIfNull(order.getPaymentId()) == 0
					&& order.getOrderStatus() == 18)
				secondConfirmUnpaidOrder = true;
				
			List<OrderDetailPo> orderDetailList = wapper
					.selectOrderDetailbyOrderId(orderId);

			List<OrderSettlementDetail> orderSettlementDetails = orderSettlementDetailWrapper
					.selectByOrderId(orderId);

			OrderSettlementDetail negativeProfitPo = orderSettlementDetails
					.stream()
					.filter(orderSettlementDetail -> orderSettlementDetail
							.getSettlement_amount().compareTo(BigDecimal.ZERO) == -1)
					.findAny().orElse(null);

			customSettlementCurrencyType = order
					.getCustomSettlementCurrencyType();

			Integer payChannelType = order.getPayChannelType();

			// 支付单可支付金额
			BigDecimal payableAmount = paymentPo.getPayableAmount();
			BigDecimal realPayableAmount = paymentPo.getRealPaidAmount();

			// 订单可支付金额
			BigDecimal paymentDetailAmount = paymentDetailPo.getPayableAmount();

			OrderSettlement expectOrderSettlement = new OrderSettlement();

			Integer orderType = this.getOrderType(orderId, orderDetailList);

			if (isShengPay) {

				expectOrderSettlement.setPay_channel_type(1);
				settleRate = "1";

				// 如果要验证盛付通结算状态，需要先分账，然后修改结算单分账状态为1
				if (settled) {

					// 盛付通分账并结算
					ShenqiSettlementService.executeShengPayMerchantSharingConvergeTask();
					orderSettlementDetailWrapper.updateShengpaySharingExecuteStatusByOrderId(orderId, 1, 0);
					ShenqiSettlementService.doSettlement();

					if (isRefunded) {

						Thread.sleep(5000);

						// 盛付通退款分账并结算
						ShenqiSettlementService.executeShengPayMerchantSharingConvergeTask();

						if (order.getAcceptTime() != null)
							orderSettlementDetailWrapper.updateShengpaySharingExecuteStatusByOrderId(orderId, 2, 1);
						else
							orderSettlementDetailWrapper.updateShengpaySharingExecuteStatusByOrderId(orderId, 1, 1);


						ShenqiSettlementService.doSettlement();
					}
				}
			} else {

				if (!Utils.nullIsCNY(order.getCurrency()).equalsIgnoreCase(
						"CNY")
						&& !Utils
								.nullIsCNY(order.getCurrency())
								.equalsIgnoreCase(paymentPo.getSettleCurrency())) {
					settleRate = realPayableAmount.divide(
							paymentPo.getRealForeignAmount(), 6,
							BigDecimal.ROUND_DOWN).toEngineeringString();
				}

				expectOrderSettlement.setPay_channel_type(0);
			}

			OrderSettlement actualOrderSettlement = orderSettlementWrapper
					.selectByPrimaryKey(orderId);

			if (gatewayPayType.equalsIgnoreCase("6401")
					&& paymentPo.getPayChannel().equalsIgnoreCase("Weixin"))
				expectOrderSettlement.setPay_channel_type(3);
			else if (gatewayPayType.equalsIgnoreCase("7200"))
				expectOrderSettlement.setPay_channel_type(5);

			if (gatewayPayType.equalsIgnoreCase("8000")) {

				if (Utils.zeroIfNull(order.getCrossBorderType()) == 1)
					expectOrderSettlement.setPay_channel_type(61);
				else if (Utils.zeroIfNull(order.getCrossBorderType()) == 2)
					expectOrderSettlement.setPay_channel_type(62);
				
				settleRate = "1";
			}

			// 判断是否所有商品都退完，非整单退款
			if (isRefunded)
				isAllRefunded = this.isAllRefunded(orderSettlementDetails,
						orderId);

			BigDecimal realOrderPaymentDetailAmount = realPayableAmount
					.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO
					: SqTradingCallService.calRealForeignAmount(
							realPayableAmount, payableAmount,
							paymentDetailAmount);

			expectOrderSettlement.setOrder_id(orderId);
			expectOrderSettlement.setPayment_id(paymentId);
			expectOrderSettlement.setTotal_amount(realOrderPaymentDetailAmount);
			expectOrderSettlement
					.setIs_foreign_exchange_bid(isForeignExchangeBid);
			expectOrderSettlement.setPay_mode_type(payMode);

			expectOrderSettlement.setCurrency(paymentPo.getSettleCurrency());
			expectOrderSettlement.setHp_settled(hpSettled);

			expectOrderSettlement
					.setMore_shop_custom_settlement_currency_type(customSettlementCurrencyType);
			expectOrderSettlement.setOrder_type(orderType);

			boolean negativeProfitUnableSettle = getNegativeProfitUnableSettle(negativeProfitPo);

			if (isAllRefunded) {
				if (settled) {

					if (negativeProfitUnableSettle) {
						expectOrderSettlement.setSettlement_status(0);
						expectOrderSettlement
								.setSettlement_result("9002:可用余额不足 可用余额不足");
					} else {
						expectOrderSettlement.setSettlement_status(1);
						expectOrderSettlement.setSettlement_result("0");
					}
				} else {
					expectOrderSettlement.setSettlement_status(0);
					expectOrderSettlement.setSettlement_result(null);
				}
			} else {

				if (settled) {

					if (negativeProfitUnableSettle) {
						expectOrderSettlement.setSettlement_status(0);
						expectOrderSettlement
								.setSettlement_result("9002:可用余额不足 可用余额不足");
					} else {
						expectOrderSettlement.setSettlement_status(1);
						expectOrderSettlement.setSettlement_result("0");
					}

				} else {
					expectOrderSettlement.setSettlement_status(0);
					expectOrderSettlement.setSettlement_result(null);
				}
			}

			expectOrderSettlement.setIs_rollback(settled
					&& expectOrderSettlement.getSettlement_status() == 2);
			expectOrderSettlement.setRollback_result(expectOrderSettlement
					.getIs_rollback() ? "0" : null);

			// 商品标价币种
			String bidCurrency = null;

			boolean isInherited = GodmchManageCallService
					.isInheritedAgent(order.getSellerId());

			ProductDetailsDto productDetailsDto = SqTradingProductService
					.getProductDetails(order.getSellerId(), orderDetailList
							.get(0).getProductId());

			// 如果是自采商品
			if (productDetailsDto.getAgentType() == 0) {

				bidCurrency = productDetailsDto.getCurrency().getCode();

				if (((Utils.zeroIfNull(customSettlementCurrencyType) == 1 || Utils
						.zeroIfNull(payChannelType) == 2) && isShengPay)) {

					settleRate = BigDecimal.ONE.divide(
							new BigDecimal(paymentPo.getExchangeRate()), 6,
							BigDecimal.ROUND_DOWN).toEngineeringString();
				} else if ((Utils.zeroIfNull(customSettlementCurrencyType) == 1 && !isShengPay)) {

					settleRate = paymentPo
							.getRealPaidAmount()
							.divide(paymentPo.getRealSubmitRmbAmount(), 6,
									BigDecimal.ROUND_DOWN)
							.toEngineeringString();
				}
			} else {

				// 所有规格的代理链条都是一样的，所以取其中一个规格获取所需的seller数量
				List<ShenqiProxyChainPo> chianPoList = isInherited ? SqTradingProductService
						.getInheritedProxyChainInfo(orderDetailList.get(0)
								.getCatalogId(), order.getSellerId())
						: SqTradingProductService
								.getProxyChainInfoList(orderDetailList.get(0)
										.getCatalogId(), order.getSellerId());

				ShenqiProxyChainPo chainPo = chianPoList
						.get(chianPoList.size() - 1);
				bidCurrency = chainPo.getCurrency();
			}

			BigDecimal realForeignAmount = realOrderPaymentDetailAmount
					.multiply(
							BigDecimal.ONE.divide(new BigDecimal(settleRate),
									6, BigDecimal.ROUND_DOWN)).setScale(6,
							BigDecimal.ROUND_DOWN);

			expectOrderSettlement.setForeign_amount(realForeignAmount.setScale(
					2, BigDecimal.ROUND_DOWN));
			expectOrderSettlement.setBatch_exchange_amount(BigDecimal.ZERO);
			expectOrderSettlement
					.setBatch_origin_foreign_amount(BigDecimal.ZERO);
			expectOrderSettlement.setExchange_rate(settleRate);

			if (Utils.emptyIfNull(paymentPo.getAppName()).equalsIgnoreCase(order.getSellerId().toString()) ||
					Utils.emptyIfNull(paymentPo.getAppName()).equalsIgnoreCase("500024716"))
				expectOrderSettlement.setIs_personal_applet(true);
			else
				expectOrderSettlement.setIs_personal_applet(false);

			// 微信直连
			if (expectOrderSettlement.getPay_channel_type() == 3) {

				expectOrderSettlement.setSettlement_result(null);
				expectOrderSettlement.setIs_personal_applet(true);
				expectOrderSettlement.setSettlement_status(1);
				expectOrderSettlement.setIs_rollback(false);
				expectOrderSettlement.setRollback_result(null);
			}
			
			// 中免澳门
			if (expectOrderSettlement.getPay_channel_type() == 5)
				expectOrderSettlement.setSettlement_result(null);
			
			// 招行支付
			if (expectOrderSettlement.getPay_channel_type() == 62
					|| expectOrderSettlement.getPay_channel_type() == 61) {

				expectOrderSettlement.setSettlement_result(null);
				expectOrderSettlement.setIs_personal_applet(true);
				bidCurrency = "CNY";
			}

			expectOrderSettlement.setBid_currency(bidCurrency);

			expectOrderSettlement
					.setCustomer_payment_order_amount(customer_payment_order_amount);
			expectOrderSettlement.setCustomer_payment_order_no(paymentPo
					.getGatewayPaymentId());
			
			if (freeOrderWithExchangeCoupon) {

				expectOrderSettlement.setExchange_rate("1");
				expectOrderSettlement.setCurrency("CNY");
				expectOrderSettlement.setSettlement_status(2);
				expectOrderSettlement.setSettlement_result(null);
				expectOrderSettlement
						.setCustomer_payment_order_amount(BigDecimal.ZERO);
			}

			// 验证order_settlement表
			ShenqiSettlementVerifyTableService.verifyOrderSettlementTable(
					expectOrderSettlement, actualOrderSettlement, settled);

			if (orderSettlementDetails.size() > 0 && isShengPay
					&& !SqTradingCallService.isCanceledOrder(order)) {

				orderTotalPlatFormFee = orderSettlementDetails
						.stream()
						.map(orderSettlementDetail -> orderSettlementDetail
								.getPlatform_fee())
						.reduce(BigDecimal.ZERO, BigDecimal::add)
						.add(orderTotalPlatFormFee);
			}
			
			this.verifyOrderSettlementDetail(paymentDetailPo, order,
					expectOrderSettlement, settled, isForeignExchangeBid,
					isRefunded, isAllRefunded, isRefundedFailed,
					isCollectingForOthersSettled, secondConfirmUnpaidOrder,
					freeOrderWithExchangeCoupon);
		}

		// 新的盛付通平台分账已经不需要该字段	2020/11/25
//		ymtSharingAmount = orderTotalPlatFormFee.subtract(Utils
//				.zeroIfNull(hpSettledReq.getSettleFee()));

		ShenqiSettlementVerifyTableService.verifyHpSettlemenNotify(
				hpSettledReq, ymtSharingAmount);
	}

	public void verifyOrderSettlementDetail(PaymentDetailPo paymentDetailPo,
			OrderPo orderPo, OrderSettlement orderSettlement, boolean settled,
			Boolean isForeignExchangeBid, Boolean isRefunded,
			Boolean isAllRefunded, Boolean isRefundedFailed,
			Boolean isCollectingForOthersSettled,
			Boolean secondConfirmUnpaidOrder,
			Boolean freeOrderWithExchangeCoupon) throws Exception {

		Logger.comment("开始构建orderSettlementDetail");

		wapper.clearCache();

		long orderId = paymentDetailPo.getOrderId();
		PaymentPo paymentPo = wapper.selectPaymentById(paymentDetailPo
				.getPaymentId());

		HashMap<String, Object> independentOrderRelationHashMap = new HashMap<>();

		long goodsOwnerId = orderPo.getGoodsOwnerId();
		Integer payMode = null;
		Integer orderType = Utils.zeroIfNull(orderSettlement.getOrder_type());

		Boolean isShengPay = false;

		if (SqTradingCallService.isShengPay(paymentPo.getGatewayPayType()))
			isShengPay = true;
		else
			isShengPay = false;

		// 货头信息
		MchInfoVo mchInfoVo = GodmchManageCallService
				.getMchInfoBySellerId(goodsOwnerId);

		String goodsOwnerCurrency = mchInfoVo.getSettlementCurrency();
		String gatewayPayType = Utils.emptyIfNull(paymentPo.getGatewayPayType());

		// GatewayPayType为6006的是支付宝支付
		if (gatewayPayType.equalsIgnoreCase("6006")
				|| gatewayPayType.equalsIgnoreCase("6012"))
			payMode = 1;
		else
			payMode = 0;

		goodsOwnerCurrency = this.convertSpecialCurrency(goodsOwnerCurrency);

		List<OrderDetailPo> orderDetailList = wapper
				.selectOrderDetailbyOrderId(orderId);
		boolean isInherited = GodmchManageCallService.isInheritedAgent(orderPo
				.getSellerId());

		// 商品结算币种
		String bidCurrency = orderSettlement.getBid_currency();
		List<ShenqiProxyChainPo> chianPoList = new ArrayList<>();

		ProductDetailsDto productDetailsDto = SqTradingProductService
				.getProductDetails(orderPo.getSellerId(), orderDetailList
						.get(0).getProductId());
		
		if (productDetailsDto.getAgentType() != 0) {

			// 所有规格的代理链条都是一样的，所以取其中一个规格获取所需的seller数量
			chianPoList = isInherited ? SqTradingProductService
					.getInheritedProxyChainInfo(orderDetailList.get(0)
							.getCatalogId(), orderPo.getSellerId())
					: SqTradingProductService
							.getProxyChainInfoList(orderDetailList.get(0)
									.getCatalogId(), orderPo.getSellerId());

			independentOrderRelationHashMap = this.isDependentOrderNew(
					chianPoList, independentOrderRelationHashMap);
		}

		// 支付单可支付金额
		BigDecimal payableAmount = paymentPo.getPayableAmount();
		BigDecimal realPayableAmount = paymentPo.getRealPaidAmount();

		// 订单可支付金额
		BigDecimal orderPaymentDetailPo = paymentDetailPo.getPayableAmount();

		BigDecimal realOrderPaymentDetailAmount = realPayableAmount
				.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO
				: SqTradingCallService.calRealForeignAmount(realPayableAmount,
						payableAmount, orderPaymentDetailPo);
		BigDecimal realOrderForeignAmount = orderSettlement.getTotal_amount();
		BigDecimal realPaymentForeignAmount = orderSettlement
				.getForeign_amount();
		
		Long fundNotCollectMerchantId = null;
		
		if (orderSettlement.getPay_channel_type() == 0) {
			
			// 获取货头是资金归集模式
			MerchantFundCollectConfigResp merchantFundCollectConfigResp = GodmchManageCallService
					.getMerchantFundCollectConfig(orderPo.getGoodsOwnerId());

			Boolean fundNotCollect = merchantFundCollectConfigResp
					.getFundNotCollect();

			if (Utils.falseIfNull(fundNotCollect))
				fundNotCollectMerchantId = merchantFundCollectConfigResp
						.getNotCollectRootMerchantId();
		}
		
		// 如果是直销商
		if (orderPo.getSellerId() == orderPo.getGoodsOwnerId()) {

			// 验证直销商OrderSettlementDetail
			this.verifyDirectMerchantOrderSettlementDetail(goodsOwnerCurrency,
					isForeignExchangeBid, orderPo, mchInfoVo,
					realOrderForeignAmount, realPaymentForeignAmount,
					paymentPo, bidCurrency, payMode, settled,
					paymentDetailPo, isShengPay, isRefunded, isAllRefunded,
					isRefundedFailed, orderDetailList, orderType,
					fundNotCollectMerchantId, secondConfirmUnpaidOrder,
					freeOrderWithExchangeCoupon);

		} else {
		
			// 验证代理订单渠道商OrderSettlementDetail
			this.verifyProxyMerchantOrderSettlementDetail(goodsOwnerCurrency,
					isForeignExchangeBid, orderPo, mchInfoVo,
					realPaymentForeignAmount, realOrderPaymentDetailAmount,
					paymentPo, bidCurrency, payMode, settled,
					paymentDetailPo, chianPoList, isShengPay,
					independentOrderRelationHashMap, isRefunded, isAllRefunded,
					isRefundedFailed, orderDetailList, orderType,
					fundNotCollectMerchantId, isCollectingForOthersSettled);
		}
	}

	public void verifyProviderSettlementDetail(
			OrderSettlementDetail orderSettlementDetail, boolean isDirect,
			boolean independentMerchant, boolean isShengPay,
			Boolean isRefunded, Boolean isBuyerServiceAmount, Boolean isRefundedFailed) throws Exception {

		// provider绑定事件需要小于3年
		long goodOwnerId = orderSettlementDetail.getGoods_owner_id();

		ProviderBean providerBean = DGSQBaseService
				.getChannelProviders(goodOwnerId);

		if (isRefunded) {
			ShenqiSettlementService
					.executeCancelProviderSettlementDetailTask();
			Thread.sleep(3000);
		}

		Long providerId = providerBean == null ? null : providerBean
				.getProviderId();

		Long orderId = orderSettlementDetail.getOrder_id();

		ProviderSettlementDetail actualProviderSettlementDetailPo = providerSettlementDetailWrapper
				.selectByOrderIdAndProviderId(orderId, providerId);

		if (independentMerchant) {

			Logger.comment("独立商家订单，providerSettlementDetail没有数据");
			DataUtil.verifyEquals(null, actualProviderSettlementDetailPo,
					"providerSettlementDetail没有数据");
		} else if (isShengPay) {

			Logger.comment("盛付通不支持软件服务商结算");
			DataUtil.verifyEquals(null, actualProviderSettlementDetailPo,
					"providerSettlementDetail没有数据");
		} else if (null == providerId) {

			Logger.comment("货头没有任何服务商");
			DataUtil.verifyEquals(null, actualProviderSettlementDetailPo,
					"providerSettlementDetail没有数据");
		} else if (9999L == providerId) {

			Logger.comment("软件服务商被禁用");
			DataUtil.verifyEquals(null, actualProviderSettlementDetailPo,
					"providerSettlementDetail没有数据");
		} else if (9998L == providerId) {

			Logger.comment("货头没有软件服务商");
			DataUtil.verifyEquals(null, actualProviderSettlementDetailPo,
					"providerSettlementDetail没有数据");
		} else if (isBuyerServiceAmount) {

			Logger.comment("买家收取服务费，没有软件服务商数据");
			DataUtil.verifyEquals(null, actualProviderSettlementDetailPo,
					"providerSettlementDetail没有数据");
		} else {

			ProviderSettlementDetail expectDetailPo = new ProviderSettlementDetail();

			String bindTime = providerBean.getBindTime();
			BigDecimal originalProfitAmount = orderSettlementDetail
					.getTotal_foreign_amount();
			String incomeCurrency = orderSettlementDetail.getForeign_currency();
			BigDecimal exchangeRate = BigDecimal.ZERO;

			// 获取provider的币种
			MchInfoVo mchInfoVo = GodmchManageCallService
					.getMchInfoBySellerId(providerId);

			String providerCurrency = mchInfoVo.getCurrency();

			// 计算provider和货头之间的平台费率差
			BigDecimal providerPlatformFeeRate = this
					.getProviderPlatformFeeRate(isDirect);
			BigDecimal goodsOwnerPlatformFeeRate = orderSettlementDetail
					.getPlatform_fee_rate();
			BigDecimal balancePlatformFeeRate = goodsOwnerPlatformFeeRate
					.subtract(providerPlatformFeeRate);

			// 20200204新需求：第一年费率差的50%，第二年费率差的30%，第三年为100%

			Calendar from = Calendar.getInstance();
			Calendar to = Calendar.getInstance();

			from.setTime(YMTDateUtil.getDate(bindTime, YMTDateUtil.YMDHMS));

			BigDecimal diffYear = YMTDateUtil.diffYear(to.getTime(),
					from.getTime());
			BigDecimal balance_platform_fee_rate_scale = BigDecimal.ZERO;

			if (diffYear.compareTo(BigDecimal.ONE) == -1)
				balance_platform_fee_rate_scale = new BigDecimal("0.50");
			else if (diffYear.compareTo(BigDecimal.ONE) >= 0
					&& diffYear.compareTo(new BigDecimal("2.00")) == -1)
				balance_platform_fee_rate_scale = new BigDecimal("0.30");
			else
				balance_platform_fee_rate_scale = new BigDecimal("1.00");

			int incomeScale = this.getScale(incomeCurrency);
			int settlementScale = this.getScale(providerCurrency);

			// 计算服务商的结算金额
			BigDecimal incomeAmount = originalProfitAmount
					.multiply(balancePlatformFeeRate)
					.multiply(new BigDecimal("0.01"))
					.multiply(balance_platform_fee_rate_scale)
					.setScale(incomeScale, BigDecimal.ROUND_DOWN);

			if (incomeCurrency.equalsIgnoreCase(providerCurrency))
				exchangeRate = BigDecimal.ONE;
			else
				exchangeRate = ShenqiSettlementService
						.getSellCurrencyVsBuyCurrencyRate(incomeCurrency,
								providerCurrency);

			BigDecimal settlementAmount = incomeAmount.multiply(exchangeRate)
					.setScale(settlementScale, BigDecimal.ROUND_DOWN);

			expectDetailPo.setProvider_id(providerId);
			expectDetailPo.setOrder_id(orderId);
			expectDetailPo.setSettlement_amount(settlementAmount.setScale(2,
					BigDecimal.ROUND_DOWN));
			expectDetailPo.setSettlement_currency(providerCurrency);
			
			if (isRefundedFailed) {
				
				expectDetailPo.setSettlement_status(orderSettlementDetail.getSettlement_status());
			} else {
				
				expectDetailPo.setSettlement_status(isRefunded ? 2
						: orderSettlementDetail.getSettlement_status());
			}
			
			if (orderSettlementDetail.getSettlement_status() == 1)
				expectDetailPo.setIs_rollback(isRefunded ? true
						: orderSettlementDetail.getIs_rollback());
			else
				expectDetailPo.setIs_rollback(orderSettlementDetail
						.getIs_rollback());

			expectDetailPo.setIncome_type(0);
			expectDetailPo.setGoods_owner_id(goodOwnerId);
			expectDetailPo
					.setProvider_platform_fee_rate(providerPlatformFeeRate);
			expectDetailPo
					.setGoods_owner_platform_fee_rate(goodsOwnerPlatformFeeRate);
			expectDetailPo.setBalance_platform_fee_rate(balancePlatformFeeRate);
			expectDetailPo.setOriginal_profit_amount(originalProfitAmount);
			expectDetailPo.setIncome_amount(incomeAmount);
			expectDetailPo.setIncome_currency(incomeCurrency);
			expectDetailPo.setIncome_and_settlement_exchange_rate(exchangeRate
					.setScale(6, BigDecimal.ROUND_DOWN));

			expectDetailPo.setNeed_exchange(providerCurrency
					.compareToIgnoreCase(incomeCurrency) != 0);
			expectDetailPo.setNeed_reset_settlement_amount(providerCurrency
					.compareToIgnoreCase(incomeCurrency) != 0);

			expectDetailPo
					.setBalance_platform_fee_rate_scale(balance_platform_fee_rate_scale);

			Logger.comment("验证Provider_id：" + expectDetailPo.getProvider_id());
			DataUtil.verifyEquals(expectDetailPo.getOrder_id(),
					actualProviderSettlementDetailPo.getOrder_id(),
					"验证Order_id");
			DataUtil.verifyDecimalEquals(expectDetailPo.getSettlement_amount(),
					actualProviderSettlementDetailPo.getSettlement_amount(),
					"验证Settlement_amount");
			DataUtil.verifyEquals(expectDetailPo.getSettlement_currency(),
					actualProviderSettlementDetailPo.getSettlement_currency(),
					"验证Settlement_currency");
			DataUtil.verifyEquals(expectDetailPo.getSettlement_status(),
					actualProviderSettlementDetailPo.getSettlement_status(),
					"验证Settlement_status");
			DataUtil.verifyEquals(expectDetailPo.getIs_rollback(),
					actualProviderSettlementDetailPo.getIs_rollback(),
					"验证Is_rollback");
			DataUtil.verifyEquals(expectDetailPo.getIncome_type(),
					actualProviderSettlementDetailPo.getIncome_type(),
					"验证Income_type");
			DataUtil.verifyEquals(expectDetailPo.getGoods_owner_id(),
					actualProviderSettlementDetailPo.getGoods_owner_id(),
					"验证Goods_owner_id");
			DataUtil.verifyDecimalEquals(expectDetailPo
					.getProvider_platform_fee_rate(),
					actualProviderSettlementDetailPo
							.getProvider_platform_fee_rate(),
					"验证Provider_platform_fee_rate");
			DataUtil.verifyDecimalEquals(expectDetailPo
					.getGoods_owner_platform_fee_rate(),
					actualProviderSettlementDetailPo
							.getGoods_owner_platform_fee_rate(),
					"验证Goods_owner_platform_fee_rate");
			DataUtil.verifyDecimalEquals(expectDetailPo
					.getBalance_platform_fee_rate(),
					actualProviderSettlementDetailPo
							.getBalance_platform_fee_rate(),
					"验证Balance_platform_fee_rate");
			DataUtil.verifyDecimalEquals(expectDetailPo.getIncome_amount(),
					actualProviderSettlementDetailPo.getIncome_amount(),
					"验证Income_amount");
			DataUtil.verifyEquals(expectDetailPo.getIncome_currency(),
					actualProviderSettlementDetailPo.getIncome_currency(),
					"验证Income_currency");
			DataUtil.verifyDecimalEquals(expectDetailPo
					.getIncome_and_settlement_exchange_rate(),
					actualProviderSettlementDetailPo
							.getIncome_and_settlement_exchange_rate(),
					"验证Income_and_settlement_exchange_rate");
			DataUtil.verifyEquals(expectDetailPo.getNeed_exchange(),
					actualProviderSettlementDetailPo.getNeed_exchange(),
					"验证Need_exchange");

			DataUtil.verifyDecimalEquals(expectDetailPo
					.getBalance_platform_fee_rate_scale(),
					actualProviderSettlementDetailPo
							.getBalance_platform_fee_rate_scale(),
					"验证Balance_platform_fee_rate_scale");

			// 校验资金流水
			AccountWapper accountWapper = new AccountWapper();

			if (expectDetailPo.getSettlement_status() == 1
					&& null != actualProviderSettlementDetailPo
							.getSettlement_time()
					&& expectDetailPo.getSettlement_amount().compareTo(
							BigDecimal.ZERO) == 1) {

				HashMap<String, Object> accountEntryMap = new HashMap<>();

				accountEntryMap.put("userId", providerId);
				accountEntryMap.put("bizcode", "360004");
				accountEntryMap.put("originalNo", orderId);

				DataUtil.verifyDecimalEquals(
						settlementAmount.setScale(2, BigDecimal.ROUND_DOWN),
						accountWapper.selectAccountEntryByMap(accountEntryMap)
								.get(0).getAmount(), "验证accountEntry日志记录");
			} else if (expectDetailPo.getSettlement_status() == 2
					&& null != actualProviderSettlementDetailPo
							.getSettlement_time()
					&& expectDetailPo.getSettlement_amount().compareTo(
							BigDecimal.ZERO) == 1) {

				HashMap<String, Object> accountEntryMap = new HashMap<>();

				accountEntryMap.put("userId", providerId);
				accountEntryMap.put("bizcode", "360004");
				accountEntryMap.put("originalNo", orderId);

				DataUtil.verifyDecimalEquals(settlementAmount, accountWapper
						.selectAccountEntryByMap(accountEntryMap).get(0)
						.getAmount(), "验证accountEntry日志记录");

				accountEntryMap.put("bizcode", "360005");

				DataUtil.verifyDecimalEquals(settlementAmount.negate(),
						accountWapper.selectAccountEntryByMap(accountEntryMap)
								.get(0).getAmount(), "验证accountEntry日志记录");
			}
		}
	}

	// 验证直销商户订单结算明细
	public void verifyDirectMerchantOrderSettlementDetail(
			String goodsOwnerCurrency, Boolean isForeignExchangeBid,
			OrderPo orderPo, MchInfoVo mchInfoVo,
			BigDecimal realOrderForeignAmount,
			BigDecimal realPaymentForeignAmount, PaymentPo paymentPo,
			String bidCurrency, int payMode, Boolean settled,
			PaymentDetailPo paymentDetailPo, boolean isShengPay,
			Boolean isRefunded, Boolean isAllRefunded,
			Boolean isRefundedFailed, List<OrderDetailPo> orderDetailList,
			Integer orderType, Long fundNotCollectMerchantId,
			Boolean secondConfirmUnpaidOrder,
			Boolean freeOrderWithExchangeCoupon) throws Exception {

		Integer customSettlementCurrencyType = orderPo
				.getCustomSettlementCurrencyType();
		Integer orderPayChannelType = orderPo.getPayChannelType();
		long orderId = orderPo.getOrderId();
		long goodsOwnerId = orderPo.getGoodsOwnerId();

		String foreignCurrency = Utils.emptyIfNull(paymentPo.getSettleCurrency());
		BigDecimal customer_payment_order_amount = paymentPo
				.getRealForeignAmount();
		String settlementCurrency = goodsOwnerCurrency;
		String gatewayPayType = Utils.emptyIfNull(paymentPo.getGatewayPayType());

		BigDecimal bidVsSettlementExchangeRate = null;
		BigDecimal settleRate = null;
		HashMap<RefundBillPo, HashMap<Long, BigDecimal>> refundBillWithRefundedProfitMap = new HashMap<>();

		ProxyIndex index = TradingSyncService.getPorxyIndexFromMongo(
				orderId, goodsOwnerId);
		BigDecimal foreignAmount = BigDecimal.ZERO;

		// 货头币种与标价支付币种之间兑换的汇率
		String foreignAndBidExchangeRate = isForeignExchangeBid ? "1"
				: settleHKRate;
		
		// 货头是否开启了分销裂变功能
		boolean isProxyFission = false;
		ProxyFissionConfig proxyFissionConfig;
		Long proxyFissionSellerId = null;

		OrderSettlementDetail expectDetailPo = new OrderSettlementDetail();

		boolean independentMerchant = mchInfoVo.getMchType() == 2;

		Boolean isBuyerServiceAmount = false;
		
		// 如果是招行支付
		if (gatewayPayType.equalsIgnoreCase("8000")) {

			if (Utils.zeroIfNull(orderPo.getCrossBorderType()) == 1)
				expectDetailPo.setPay_channel_type(61);
			else if (Utils.zeroIfNull(orderPo.getCrossBorderType()) == 2)
				expectDetailPo.setPay_channel_type(62);
			
			foreignAndBidExchangeRate = "1";
		}
		
		// 如果是盛付通
		if (isShengPay) {

			foreignAmount = realOrderForeignAmount;
			goodsOwnerCurrency = "CNY";
			expectDetailPo.setPay_channel_type(1);
			foreignAndBidExchangeRate = "1";

			if (null != customSettlementCurrencyType
					|| Utils.zeroIfNull(orderPayChannelType) == 2) {

				foreignAmount = realPaymentForeignAmount;
				foreignAndBidExchangeRate = BigDecimal.ONE
						.divide(new BigDecimal(paymentPo.getExchangeRate()),
								MathContext.DECIMAL32)
						.setScale(7, BigDecimal.ROUND_HALF_DOWN)
						.toEngineeringString();
			}

			settlementCurrency = "CNY";
			foreignCurrency = "CNY";
		} else {
			
			if (Utils.zeroIfNull(customSettlementCurrencyType) == 1) {

				foreignAmount = realPaymentForeignAmount;
				foreignAndBidExchangeRate = paymentPo
						.getRealPaidAmount()
						.divide(paymentPo.getRealForeignAmount(), 7,
								BigDecimal.ROUND_DOWN).toEngineeringString();
			} else if (!bidCurrency.equalsIgnoreCase(settlementCurrency)
					&& !bidCurrency.equalsIgnoreCase("CNY")) {

				foreignAmount = realPaymentForeignAmount;

				foreignAndBidExchangeRate = paymentPo
						.getRealPaidAmount()
						.divide(paymentPo.getRealForeignAmount(), 6,
								BigDecimal.ROUND_DOWN).toEngineeringString();
			} else {

				foreignAmount = index.getIncome().divide(
						new BigDecimal(foreignAndBidExchangeRate), 2,
						BigDecimal.ROUND_DOWN);
			}

			expectDetailPo.setPay_channel_type(0);
		}

		// 如果是微信直连
		if (gatewayPayType.equalsIgnoreCase("6401")
				&& paymentPo.getPayChannel().equalsIgnoreCase("Weixin"))
			expectDetailPo.setPay_channel_type(3);

		// 如果是澳门中银
		if (gatewayPayType.equalsIgnoreCase("7200"))
			expectDetailPo.setPay_channel_type(5);

		Boolean needExchange = !foreignCurrency
				.equalsIgnoreCase(goodsOwnerCurrency);
		
		if (freeOrderWithExchangeCoupon)
			needExchange = false;

		if (needExchange) {

			settleRate = ShenqiSettlementService
					.getSellCurrencyVsBuyCurrencyRate(foreignCurrency,
							goodsOwnerCurrency);
			bidVsSettlementExchangeRate = ShenqiSettlementService
					.getSellCurrencyVsBuyCurrencyRate(bidCurrency,
							goodsOwnerCurrency);
		} else {

			settleRate = BigDecimal.ONE;

			if (Utils.zeroIfNull(customSettlementCurrencyType) == 1
					&& !isShengPay)
				bidVsSettlementExchangeRate = BigDecimal.ONE;
			else
				bidVsSettlementExchangeRate = BigDecimal.ONE.divide(
						new BigDecimal(foreignAndBidExchangeRate), 6, BigDecimal.ROUND_DOWN);
		}

		int foreignAmountScale = 2;

		if (freeOrderWithExchangeCoupon)
			foreignAmountScale = 2;
		else
			foreignAmountScale = this.getScale(paymentPo.getSettleCurrency());

		OrderSettlementDetail actualDetailPo = null;

		if (secondConfirmUnpaidOrder) {

			actualDetailPo = orderSettlementDetailWrapper
					.selectSecondConfirmUnpaidOrderByOrderIdAndUserId(orderId,
							goodsOwnerId);
			expectDetailPo.setCustomer_payment_order_amount(null);
			expectDetailPo.setCustomer_payment_order_no(null);
		} else {

			actualDetailPo = orderSettlementDetailWrapper
					.selectByOrderIdAndUserId(orderId,
							goodsOwnerId);

			expectDetailPo
					.setCustomer_payment_order_amount(customer_payment_order_amount);
			expectDetailPo.setCustomer_payment_order_no(paymentPo
					.getGatewayPaymentId());
		}
		
		expectDetailPo.setOrder_id(orderId);
		expectDetailPo.setUser_id(goodsOwnerId);
		expectDetailPo.setTotal_foreign_amount(foreignAmount.setScale(
				foreignAmountScale, BigDecimal.ROUND_DOWN));
		expectDetailPo.setTotal_rmb_amount(index.getIncome());
		expectDetailPo.setForeign_currency(foreignCurrency);
		expectDetailPo.setExchange_rate(settleRate.toPlainString());
		expectDetailPo.setSettlement_currency(settlementCurrency);
		expectDetailPo.setBid_currency(bidCurrency);

		expectDetailPo.setUser_currency(goodsOwnerCurrency);
		expectDetailPo.setUser_country(mchInfoVo.getCountryCode());

		expectDetailPo.setPay_mode_type(payMode);
		expectDetailPo.setIs_platform_supplier(false);

		if (isAllRefunded) {
			expectDetailPo.setSettlement_status(settled ? 1 : 0);
		} else {
			
			expectDetailPo.setSettlement_status(settled ? 1 : 0);
		}

		expectDetailPo.setIs_rollback(settled
				&& expectDetailPo.getSettlement_status() == 2);
		expectDetailPo.setGoods_owner_id(goodsOwnerId);
		expectDetailPo.setParent_proxy_id(null);
		expectDetailPo.setUser_role("GOODS_OWNER");

		BigDecimal whiteGoodsOwnerIdFeeRate = this.getWhitelistMerchantRateNew(
				expectDetailPo.getPay_channel_type(),
				goodsOwnerId, false, independentMerchant, payMode,
				orderType);

		if (independentMerchant) {

			expectDetailPo.setPlatform_fee_rate(this.getPlatformFeeRateNew(
					expectDetailPo.getPay_channel_type(),
					goodsOwnerId, true, independentMerchant,
					false, null, payMode, orderType));
			expectDetailPo.setIs_proxy_share_fee_merchant(false);
		} else {

			// 如果是白名单商户则使用白名单设置的rate
			if (whiteGoodsOwnerIdFeeRate == null) {

				expectDetailPo.setPlatform_fee_rate(this.getPlatformFeeRateNew(
						expectDetailPo.getPay_channel_type(),
						goodsOwnerId, true, independentMerchant,
						false, null, payMode, orderType));
			} else {

				expectDetailPo.setPlatform_fee_rate(whiteGoodsOwnerIdFeeRate);
			}
		}

		expectDetailPo.setIs_proxy_share_fee_merchant(false);

		if (Utils.zeroIfNull(orderPo.getServiceAmount()).compareTo(
				BigDecimal.ZERO) == 1) {

			expectDetailPo.setPlatform_fee_rate(BigDecimal.ZERO);
			expectDetailPo.setRemark("买家承担手续费，不向商家收费");
			isBuyerServiceAmount = true;
		}

		if (expectDetailPo.getPay_channel_type() == 3
				|| expectDetailPo.getPay_channel_type() == 5)
			expectDetailPo.setPlatform_fee_rate(BigDecimal.ZERO);

		expectDetailPo.setOrder_foreign_amount(realPaymentForeignAmount);
		expectDetailPo.setIs_proxy_product(false);
		expectDetailPo.setNeed_exchange(needExchange);
		expectDetailPo
				.setForeign_and_bid_exchange_rate(foreignAndBidExchangeRate);
		expectDetailPo
				.setMore_shop_custom_settlement_currency_type(customSettlementCurrencyType);
		expectDetailPo
				.setBid_vs_settlement_exchange_rate(bidVsSettlementExchangeRate
						.setScale(6, BigDecimal.ROUND_UP));

		// 获得小数位数
		int scale = this.getScale(expectDetailPo.getSettlement_currency());

		// 如果是独立商户或者白名单商户，则使用订单总额 × 费率
		if (independentMerchant || whiteGoodsOwnerIdFeeRate != null) {

			expectDetailPo.setPlatform_fee(paymentPo.getRealForeignAmount()
					.multiply(expectDetailPo.getPlatform_fee_rate())
					.multiply(new BigDecimal("0.01"))
					.setScale(scale, BigDecimal.ROUND_UP));

			if (independentMerchant)
				expectDetailPo.setIs_dependent_merchant(true);
			else
				expectDetailPo.setIs_dependent_merchant(false);

		} else {

			if (Utils.zeroIfNull(customSettlementCurrencyType) == 1
					&& !isShengPay) {

				expectDetailPo.setPlatform_fee(expectDetailPo
						.getTotal_rmb_amount()
						.multiply(expectDetailPo.getPlatform_fee_rate())
						.multiply(new BigDecimal("0.01"))
						.setScale(scale, BigDecimal.ROUND_UP));
			} else {
				
				if (expectDetailPo.getPay_channel_type() == 61
						|| expectDetailPo.getPay_channel_type() == 62) {

					expectDetailPo.setPlatform_fee(expectDetailPo
							.getTotal_foreign_amount()
							.multiply(bidVsSettlementExchangeRate)
							.multiply(expectDetailPo.getPlatform_fee_rate())
							.multiply(new BigDecimal("0.01"))
							.setScale(scale, BigDecimal.ROUND_UP));
				} else {

					expectDetailPo.setPlatform_fee(expectDetailPo
							.getTotal_foreign_amount()
							.multiply(expectDetailPo.getPlatform_fee_rate())
							.multiply(new BigDecimal("0.01"))
							.setScale(scale, BigDecimal.ROUND_UP));
				}
			}

			expectDetailPo.setIs_dependent_merchant(false);
		}

		if (expectDetailPo.getSettlement_currency().equalsIgnoreCase("CNY")) {

			if (whiteGoodsOwnerIdFeeRate != null) {

				expectDetailPo.setRemark("直销订单费率不能分摊,由货头自己承担.");
			} else if (expectDetailPo.getTotal_rmb_amount().compareTo(
					new BigDecimal("0.01")) == 0) {

				expectDetailPo.setPlatform_fee(BigDecimal.ZERO);
				expectDetailPo.setRemark("渠道商结算金额等于0.01,不收平台费");
			} else if (expectDetailPo.getTotal_rmb_amount().compareTo(
					expectDetailPo.getPlatform_fee()) <= 0) {

				expectDetailPo.setPlatform_fee(BigDecimal.ZERO);
				expectDetailPo.setRemark("平台费大于或等于渠道商结算金额,不收平台费");
			}

			if ((Utils.zeroIfNull(customSettlementCurrencyType) == 1 || Utils
					.zeroIfNull(orderPayChannelType) == 2) && isShengPay) {
				expectDetailPo.setSettlement_amount(expectDetailPo
						.getTotal_rmb_amount()
						.multiply(expectDetailPo.getBid_vs_settlement_exchange_rate())
						.subtract(expectDetailPo.getPlatform_fee())
						.setScale(scale, BigDecimal.ROUND_DOWN));
			} else {
				
				expectDetailPo.setSettlement_amount(expectDetailPo
						.getTotal_rmb_amount()
						.subtract(expectDetailPo.getPlatform_fee())
						.setScale(scale, BigDecimal.ROUND_DOWN));
			}
		} else {

			if (whiteGoodsOwnerIdFeeRate != null) {

				expectDetailPo.setRemark("直销订单费率不能分摊,由货头自己承担.");
			} else if (expectDetailPo.getTotal_foreign_amount().compareTo(
					new BigDecimal("0.01")) == 0) {

				expectDetailPo.setPlatform_fee(BigDecimal.ZERO);
				expectDetailPo.setRemark("渠道商结算金额等于0.01,不收平台费");
			} else if (expectDetailPo.getTotal_foreign_amount().compareTo(
					expectDetailPo.getPlatform_fee()) <= 0) {

				expectDetailPo.setPlatform_fee(BigDecimal.ZERO);
				expectDetailPo.setRemark("平台费大于或等于渠道商结算金额,不收平台费");
			}

			if (Utils.zeroIfNull(customSettlementCurrencyType) == 1
					&& !isShengPay) {

				if (expectDetailPo.getBid_currency()
						.equalsIgnoreCase(expectDetailPo.getSettlement_currency()))
					expectDetailPo.setSettlement_amount(expectDetailPo
							.getTotal_rmb_amount()
							.subtract(expectDetailPo.getPlatform_fee())
							.setScale(scale, BigDecimal.ROUND_DOWN));
				else
					expectDetailPo.setSettlement_amount(expectDetailPo
							.getTotal_foreign_amount()
							.subtract(expectDetailPo.getPlatform_fee())
							.setScale(scale, BigDecimal.ROUND_DOWN));
			} else {

				if (expectDetailPo.getPay_channel_type() == 61
						|| expectDetailPo.getPay_channel_type() == 62) {

					expectDetailPo.setSettlement_amount(expectDetailPo
							.getTotal_foreign_amount()
							.multiply(bidVsSettlementExchangeRate)
							.subtract(expectDetailPo.getPlatform_fee())
							.setScale(scale, BigDecimal.ROUND_DOWN));
				} else {

					expectDetailPo.setSettlement_amount(expectDetailPo
							.getTotal_foreign_amount()
							.subtract(expectDetailPo.getPlatform_fee())
							.setScale(scale, BigDecimal.ROUND_DOWN));
				}
			}
		}

		if (Utils.emptyIfNull(paymentPo.getAppName()).equalsIgnoreCase(String.valueOf(goodsOwnerId)) ||
				Utils.emptyIfNull(paymentPo.getAppName()).equalsIgnoreCase("500024716"))
			expectDetailPo.setIs_personal_applet(true);
		else
			expectDetailPo.setIs_personal_applet(false);

		expectDetailPo.setPayment_id(paymentDetailPo.getPaymentId());
		expectDetailPo.setBiz_id(String.valueOf(orderId));
		
		if (secondConfirmUnpaidOrder)
			expectDetailPo.setSettlement_type(12);
		else
			expectDetailPo.setSettlement_type(0);

		// 微信直连
		if (expectDetailPo.getPay_channel_type() == 3) {

			expectDetailPo.setIs_personal_applet(true);
			expectDetailPo.setBid_vs_settlement_exchange_rate(BigDecimal.ONE);
			expectDetailPo.setRemark("微信直连不收手续费");
		} else if (expectDetailPo.getPay_channel_type() == 5)
			expectDetailPo.setRemark("中银澳门不收手续费");
		else if (expectDetailPo.getPay_channel_type() == 62
				|| expectDetailPo.getPay_channel_type() == 61) {
			expectDetailPo.setIs_personal_applet(true);
		}
		
		expectDetailPo.setFund_not_collect_merchant_id(fundNotCollectMerchantId);
		expectDetailPo.setSettlement_way(0);
		
		if (freeOrderWithExchangeCoupon) {

			expectDetailPo.setForeign_currency("CNY");
			expectDetailPo.setSettlement_status(2);
			expectDetailPo.setRemark(null);
			expectDetailPo.setForeign_and_bid_exchange_rate("1.00");
			expectDetailPo.setBid_vs_settlement_exchange_rate(BigDecimal.ONE);
		}

		ShenqiSettlementVerifyTableService.verifyOrderSettlementDetailTable(
				expectDetailPo, actualDetailPo);
		
		// 获取代理裂变配置
		proxyFissionConfig = proxyFissionConfigWrapper
				.selectLatestByMerchantId(goodsOwnerId);
		
		// 如果开启了代理裂变配置且为内购
		if (null != proxyFissionConfig && orderPo.getShenqiProxyBuyOrder()) {

			isProxyFission = true;
			proxyFissionSellerId = orderPo.getUserId();
		}
		
		if (isRefunded) {
			Logger.comment("验证退货退款结算单");

			List<RefundBillPo> refundBillPoList = wapper
					.selectRefundBillListByOrderId(orderId);

			for (RefundBillPo refundBillPo : refundBillPoList) {

				HashMap<Long, BigDecimal> refundedProfitMap = RefundService
						.getRefundedProfit(refundBillPo, orderPo);

				this.verifyRefundedOrderSettlementDetail(refundBillPo,
						actualDetailPo, orderPo, refundedProfitMap,
						orderDetailList, null);

				if (isRefundedFailed) {

					String refundBillNo = refundBillPo.getRefundBillNo();

					if (expectDetailPo.getSettlement_status() == 2) {

						// 结算表有多条用户的结算数据，根据actualList的大小判断
						this.verifyRefundedFailedOrderSettlementDetail(
								actualDetailPo,
								String.valueOf(expectDetailPo.getOrder_id()), 0);
					} else {

						// 结算表有多条用户的结算数据，根据actualList的大小判断
						this.verifyRefundedFailedOrderSettlementDetail(
								actualDetailPo, refundBillNo, 0);
					}
				}

				refundBillWithRefundedProfitMap.put(refundBillPo,
						refundedProfitMap);
			}
		}
		
		if (isProxyFission)
			this.verifyPromotersOrderSettlementDetail(actualDetailPo,
					proxyFissionConfig, orderPo.getUserId(), orderDetailList,
					orderPo.getPayableAmount(), proxyFissionSellerId,
					isRefunded, refundBillWithRefundedProfitMap, orderPo.getShenqiProxyBuyOrder());

		// 验证ProviderSettlementDetail
		this.verifyProviderSettlementDetail(actualDetailPo, true,
				independentMerchant, isShengPay, isRefunded,
				isBuyerServiceAmount, isRefundedFailed);
	}

	// 验证代理商户订单结算明细
	public void verifyProxyMerchantOrderSettlementDetail(
			String goodsOwnerCurrency, Boolean isForeignExchangeBid,
			OrderPo orderPo, MchInfoVo mchInfoVo,
			BigDecimal realOrderForeignAmount,
			BigDecimal realOrderPaymentDetailAmount, PaymentPo paymentPo,
			String bidCurrency, int payMode, Boolean settled,
			PaymentDetailPo paymentDetailPo,
			List<ShenqiProxyChainPo> chianPoList, boolean isShengPay,
			HashMap<String, Object> independentOrderRelationHashMap,
			Boolean isRefunded, Boolean isAllRefunded,
			Boolean isRefundedFailed, List<OrderDetailPo> orderDetailList,
			Integer orderType, Long fundNotCollectMerchantId,
			Boolean isCollectingForOthersSettled) throws Exception {

		Long goodsOwnerChildId = null;
		BigDecimal agentRate = null;
		BigDecimal goodsOwnerChildFeeRate = null;
		BigDecimal customer_payment_order_amount = paymentPo
				.getRealForeignAmount();
		String foreignCurrency = paymentPo.getSettleCurrency();
		BigDecimal bidVsSettlementExchangeRate;
		GoodsOwnerSettlementConfig goodsOwnerSettlementConfig = null;
		boolean negativeProfitUnableSettle = false;
		Long chargeIndependentMerchantId = null;
		OrderSettlementDetail chargeIndependentMerchantOrderSettlementDetail = null;

		// 货头是否开启了分销裂变功能
		boolean isProxyFission = false;
		ProxyFissionConfig proxyFissionConfig = null;
		Long proxyFissionSellerId = null;

		// 货头币种与标价支付币种之间兑换的汇率
		String foreignAndBidExchangeRate = isForeignExchangeBid ? "1"
				: settleHKRate;
		
		BigDecimal whiteGoodsOwnerIdFeeRate = null;
		Boolean isGoodsOwnerChildIdAmountNotEnough = false;
		OrderSettlementDetail whiteGoodsOwnerIdOrderSettlementDetail = null;
		
		// 平台供货商订单
		boolean isPlatformSupplierOrder = (Utils.zeroIfNull(orderPo
							.getOrderFlags()) & 1 << 2) > 0;
							
		ArrayList<PlatformProductDetail> platformProductDetailList = new ArrayList<PlatformProductDetail>();

		ArrayList<OrderSettlementDetail> actualList = new ArrayList<OrderSettlementDetail>();
		ArrayList<OrderSettlementDetail> expectList = new ArrayList<OrderSettlementDetail>();

		boolean isIndependentOrder = Utils
				.falseIfNull((Boolean) independentOrderRelationHashMap
						.get("isIndependentOrder"));
		
		@SuppressWarnings("unchecked")
		ArrayList<IndependentMerchantInfoBean> independentMerchantInfos = (ArrayList<IndependentMerchantInfoBean>) independentOrderRelationHashMap
				.get("independentMerchantInfos");

		for (int i = 0; i < independentMerchantInfos.size(); i++) {

			if (i == independentMerchantInfos.size() - 1)
				independentMerchantInfos.get(i).setChargeIndependentMerchant(
						true);
			else
				independentMerchantInfos.get(i).setChargeIndependentMerchant(
						false);
		}

		HashMap<RefundBillPo, HashMap<Long, BigDecimal>> refundBillWithRefundedProfitMap = new HashMap<>();

		if (isRefunded) {
			List<RefundBillPo> refundBillPoList = wapper
					.selectRefundBillListByOrderId(orderPo.getOrderId());

			for (RefundBillPo refundBillPo : refundBillPoList) {

				HashMap<Long, BigDecimal> refundedProfitMap = RefundService
						.getRefundedProfit(refundBillPo, orderPo);
				refundBillWithRefundedProfitMap.put(refundBillPo,
						refundedProfitMap);
			}
		}

		for (int i = 0; i < chianPoList.size(); i++) {

			ShenqiProxyChainPo chainPo = chianPoList.get(i);
			long sellerId = chainPo.getSellerId();
			boolean isGoodsOwner = false;
			BigDecimal platformFee = BigDecimal.ZERO;
			BigDecimal settleRate = BigDecimal.ZERO;

			ProxyIndex index = TradingSyncService.getPorxyIndexFromMongo(
					orderPo.getOrderId(), sellerId);
			OrderSettlementDetail actualDetailPo = orderSettlementDetailWrapper
					.selectByOrderIdAndUserId(orderPo.getOrderId(), sellerId);
			OrderSettlementDetail expectDetailPo = new OrderSettlementDetail();

			if (index.getSellerRole() == 2)
				isGoodsOwner = true;

			BigDecimal totalRMBAmount = index.getIncome();
			BigDecimal foreignAmount = BigDecimal.ZERO;

			mchInfoVo = GodmchManageCallService
					.getMchInfoBySellerId(sellerId);

			List<IndependentMerchantInfoBean> independentMerchantInfoList = independentMerchantInfos
					.stream()
					.filter(info -> info.getMchInfoVo().getMchId() == sellerId)
					.collect(Collectors.toList());

			// 是否为独立商家
			boolean independentMerchant = independentMerchantInfoList.size() > 0;

			// 收费的独立商家
			boolean chargeIndependentMerchant = false;

			if (independentMerchant
					&& independentMerchantInfoList.get(0)
							.getChargeIndependentMerchant()) {
				
				chargeIndependentMerchant = true;
				goodsOwnerSettlementConfig = goodsOwnerSettlementConfigWrapper
						.selectByMerchantId(sellerId);
				chargeIndependentMerchantId = sellerId;
			}

			String sellerCurrency = mchInfoVo.getCurrency();
			String userCountry = mchInfoVo.getCountryCode();

			// 如果是盛付通
			if (isShengPay) {

				sellerCurrency = "CNY";
				goodsOwnerCurrency = "CNY";
				foreignAndBidExchangeRate = "1";

				expectDetailPo.setPay_channel_type(1);
				foreignAmount = totalRMBAmount;

			} else {

				if (!bidCurrency.equalsIgnoreCase(goodsOwnerCurrency)
						&& !bidCurrency.equalsIgnoreCase("CNY")) {

					foreignAndBidExchangeRate = paymentPo
							.getRealPaidAmount()
							.divide(paymentPo.getRealForeignAmount(), 6,
									BigDecimal.ROUND_DOWN)
							.toEngineeringString();

					realOrderForeignAmount = paymentPo.getRealPaidAmount()
							.multiply(
									BigDecimal.ONE.divide(new BigDecimal(
											foreignAndBidExchangeRate), 6,
											BigDecimal.ROUND_DOWN));
				}
				
				foreignAmount = totalRMBAmount.multiply(BigDecimal.ONE.divide(
						new BigDecimal(foreignAndBidExchangeRate),
						MathContext.DECIMAL32).setScale(6,
						BigDecimal.ROUND_DOWN)).setScale(6, BigDecimal.ROUND_DOWN);

				expectDetailPo.setPay_channel_type(0);
			}

			sellerCurrency = this.convertSpecialCurrency(sellerCurrency);

			Boolean needExchange = !foreignCurrency.equalsIgnoreCase(sellerCurrency);

			// 获得结算金额的小数位数
			int settlementAmountScale = this.getScale(sellerCurrency);

			// 获得结算金额的小数位数
			int foreignAmountScale = this.getScale(foreignCurrency);

			if (needExchange) {

				settleRate = ShenqiSettlementService
						.getSellCurrencyVsBuyCurrencyRate(foreignCurrency,
								sellerCurrency);

				if (bidCurrency.equalsIgnoreCase(sellerCurrency)) {

					if (!bidCurrency.equalsIgnoreCase(goodsOwnerCurrency)
							&& !bidCurrency.equalsIgnoreCase("CNY"))
						settleRate = new BigDecimal(foreignAndBidExchangeRate);
					else
						settleRate = new BigDecimal(settleHKRate);
				}

			} else {

				settleRate = BigDecimal.ONE;
			}

			if (bidCurrency.equalsIgnoreCase(sellerCurrency))
				bidVsSettlementExchangeRate = BigDecimal.ONE;
			else {

				if (needExchange) {

					bidVsSettlementExchangeRate = ShenqiSettlementService
							.getSellCurrencyVsBuyCurrencyRate(bidCurrency,
									sellerCurrency);
				} else

					bidVsSettlementExchangeRate = BigDecimal.ONE.divide(
							new BigDecimal(foreignAndBidExchangeRate), 4, BigDecimal.ROUND_DOWN);
			}

			expectDetailPo
					.setCustomer_payment_order_amount(customer_payment_order_amount);
			expectDetailPo.setCustomer_payment_order_no(paymentPo
					.getGatewayPaymentId());

			expectDetailPo.setOrder_id(orderPo.getOrderId());
			expectDetailPo.setUser_id(sellerId);

			expectDetailPo.setTotal_foreign_amount(foreignAmount.setScale(
					foreignAmountScale, BigDecimal.ROUND_DOWN));

			expectDetailPo.setTotal_rmb_amount(totalRMBAmount);
			expectDetailPo.setForeign_currency(paymentPo.getSettleCurrency());
			expectDetailPo.setSettlement_currency(sellerCurrency);
			expectDetailPo.setBid_currency(bidCurrency);

			expectDetailPo.setUser_currency(sellerCurrency);
			expectDetailPo.setUser_country(userCountry);
			expectDetailPo.setNeed_exchange(needExchange);

			expectDetailPo.setPay_mode_type(payMode);

			expectDetailPo
					.setForeign_and_bid_exchange_rate(foreignAndBidExchangeRate);

			if (isAllRefunded) {
				expectDetailPo.setSettlement_status(settled ? 1 : 0);
			} else {

				expectDetailPo.setSettlement_status(settled ? 1 : 0);
			}

			expectDetailPo.setIs_rollback(settled && expectDetailPo.getSettlement_status() == 2 );
			expectDetailPo.setGoods_owner_id(orderPo.getGoodsOwnerId());
			expectDetailPo.setParent_proxy_id(index.getSellerRole() == 2 ? null
					: (long) wapper.selectProxyChainbyOrderIdAndChildId(
							orderPo.getOrderId(), sellerId).getSellerId());
			expectDetailPo
					.setUser_role(index.getSellerRole() == 2 ? "GOODS_OWNER"
							: "PROXY");
			
			if (isIndependentOrder) {

				if (independentMerchant) {

					if (chargeIndependentMerchant)
						expectDetailPo.setPlatform_fee_rate(this
								.getPlatformFeeRateNew(
										expectDetailPo.getPay_channel_type(),
										sellerId, false,
										chargeIndependentMerchant, false, null,
										payMode, orderType));
					else
						expectDetailPo.setPlatform_fee_rate(BigDecimal.ZERO);

				} else
					expectDetailPo.setPlatform_fee_rate(BigDecimal.ZERO);

			} else {
				
				if (isPlatformSupplierOrder) {

					if (i == 1)
						whiteGoodsOwnerIdFeeRate = this
								.getWhitelistMerchantRateNew(
										expectDetailPo.getPay_channel_type(),
										sellerId, false, independentMerchant,
										payMode, orderType);
				} else {

					whiteGoodsOwnerIdFeeRate = this
							.getWhitelistMerchantRateNew(
									expectDetailPo.getPay_channel_type(),
									orderPo.getGoodsOwnerId(), false,
									independentMerchant, payMode, orderType);
				}
				
				if (whiteGoodsOwnerIdFeeRate == null) {

					if (isGoodsOwner && !isPlatformSupplierOrder)
						expectDetailPo.setPlatform_fee_rate(this
								.getPlatformFeeRateNew(
										expectDetailPo.getPay_channel_type(),
										orderPo.getGoodsOwnerId(), false,
										chargeIndependentMerchant,
										false,
										null, payMode,
										orderType));
					else {
						
						if (isPlatformSupplierOrder && i == 1) {
							
							expectDetailPo.setPlatform_fee_rate(this
									.getPlatformFeeRateNew(expectDetailPo
											.getPay_channel_type(), sellerId,
											false, chargeIndependentMerchant,
											false, null, payMode, orderType));
						} else
							expectDetailPo.setPlatform_fee_rate(BigDecimal.ZERO);
					}
				} else {

					/*
					 * 如果是白名单用户，则货头的费率=白名单的费率-第一个下级的费率；第一个下级的费率=货头的费率 ×
					 * 税费比率；其他下级的费率为0；如果第一个下级的结算金额不足以覆盖手续费，则所有手续费由货头承担
					 */
					if (isGoodsOwner && !isPlatformSupplierOrder) {

						goodsOwnerChildId = index.getChildSellerId();
						agentRate = GodmchManageCallService
								.getAgentRate(orderPo.getGoodsOwnerId(),
										goodsOwnerChildId);
						goodsOwnerChildFeeRate = whiteGoodsOwnerIdFeeRate
								.multiply(agentRate).multiply(
										new BigDecimal("0.01"));

						expectDetailPo
								.setPlatform_fee_rate(whiteGoodsOwnerIdFeeRate
										.subtract(goodsOwnerChildFeeRate));
						expectDetailPo.setIs_proxy_share_fee_merchant(true);

						whiteGoodsOwnerIdOrderSettlementDetail = expectDetailPo;

					} else if (i == 1 && isPlatformSupplierOrder) {

						goodsOwnerChildId = index.getChildSellerId();
						agentRate = GodmchManageCallService
								.getAgentRate(sellerId,
										goodsOwnerChildId);
						goodsOwnerChildFeeRate = whiteGoodsOwnerIdFeeRate
								.multiply(Utils.zeroIfNull(agentRate)).multiply(
										new BigDecimal("0.01"));

						expectDetailPo
								.setPlatform_fee_rate(whiteGoodsOwnerIdFeeRate
										.subtract(goodsOwnerChildFeeRate));
						expectDetailPo.setIs_proxy_share_fee_merchant(true);

						whiteGoodsOwnerIdOrderSettlementDetail = expectDetailPo;

					} else if (sellerId == goodsOwnerChildId) {

						expectDetailPo
								.setPlatform_fee_rate(goodsOwnerChildFeeRate);
						expectDetailPo.setIs_proxy_share_fee_merchant(true);
					} else {

						expectDetailPo.setPlatform_fee_rate(BigDecimal.ZERO);
						expectDetailPo.setIs_proxy_share_fee_merchant(false);
					}
				}
			}

			expectDetailPo.setIs_proxy_product(index.getSellerRole() != 2);

			if (independentMerchant)
				expectDetailPo.setIs_dependent_merchant(true);
			else
				expectDetailPo.setIs_dependent_merchant(false);

			if (independentMerchant && chargeIndependentMerchant) {

				platformFee = realOrderPaymentDetailAmount
						.multiply(bidVsSettlementExchangeRate)
						.multiply(expectDetailPo.getPlatform_fee_rate())
						.multiply(new BigDecimal("0.01"));

				expectDetailPo.setPlatform_fee(platformFee.setScale(
						settlementAmountScale, BigDecimal.ROUND_UP));
				
			} else if (Utils.falseIfNull(expectDetailPo
					.getIs_proxy_share_fee_merchant())) {

				platformFee = realOrderPaymentDetailAmount
						.multiply(bidVsSettlementExchangeRate)
						.multiply(expectDetailPo.getPlatform_fee_rate())
						.multiply(new BigDecimal("0.01"));

				expectDetailPo.setPlatform_fee(platformFee.setScale(
						settlementAmountScale, BigDecimal.ROUND_UP));
				
			} else if (Utils.zeroIfNull(orderType) == 1
					|| Utils.zeroIfNull(orderType) == 2) {

				platformFee = realOrderPaymentDetailAmount
						.multiply(bidVsSettlementExchangeRate)
						.multiply(expectDetailPo.getPlatform_fee_rate())
						.multiply(new BigDecimal("0.01"));

				expectDetailPo.setPlatform_fee(platformFee.setScale(
						settlementAmountScale, BigDecimal.ROUND_UP));
				
			} else if (isPlatformSupplierOrder) {

				platformFee = realOrderPaymentDetailAmount
						.multiply(bidVsSettlementExchangeRate)
						.multiply(expectDetailPo.getPlatform_fee_rate())
						.multiply(new BigDecimal("0.01"));

				expectDetailPo.setPlatform_fee(platformFee.setScale(
						settlementAmountScale, BigDecimal.ROUND_UP));
			} else {

				platformFee = expectDetailPo.getTotal_rmb_amount()
						.multiply(bidVsSettlementExchangeRate)
						.multiply(expectDetailPo.getPlatform_fee_rate())
						.multiply(new BigDecimal("0.01"));

				expectDetailPo.setPlatform_fee(platformFee.setScale(
						settlementAmountScale, BigDecimal.ROUND_UP));
			}

			if (isIndependentOrder) {

				// 平台费用最少收0.01，如果结算金额等于0.01，则不收服务费
				if (independentMerchant && chargeIndependentMerchant) {

					if (expectDetailPo.getPlatform_fee().compareTo(
							new BigDecimal("0.01")) == -1)
						expectDetailPo.setPlatform_fee(new BigDecimal("0.01")
								.setScale(settlementAmountScale,
										BigDecimal.ROUND_UP));
					else {

						expectDetailPo.setRemark(null);
					}
				}
			} else {

				// 平台费用最少收0.01，如果结算金额等于0.01，则不收服务费
				if (isGoodsOwner) {
					if (whiteGoodsOwnerIdFeeRate != null) {
						expectDetailPo
								.setRemark(String
										.format("渠道商费率:%s,代理商费率:%s,代理商费率比例值:%s,childSellerId:%s",
												whiteGoodsOwnerIdFeeRate,
												goodsOwnerChildFeeRate
														.setScale(
																3,
																BigDecimal.ROUND_HALF_UP),
												agentRate,
												goodsOwnerChildId));
					} else
						expectDetailPo.setRemark(null);
				} else {
					
					if (i == 1 && isPlatformSupplierOrder && whiteGoodsOwnerIdFeeRate != null) {
						expectDetailPo
								.setRemark(String
										.format("渠道商费率:%s,代理商费率:%s,代理商费率比例值:%s,childSellerId:%s",
												whiteGoodsOwnerIdFeeRate,
												goodsOwnerChildFeeRate
														.setScale(
																3,
																BigDecimal.ROUND_HALF_UP),
												agentRate,
												goodsOwnerChildId));
					} else
						expectDetailPo.setRemark(null);
				}
			}

			if (isIndependentOrder) {

				if (!independentMerchant || !chargeIndependentMerchant)
					expectDetailPo.setRemark("独立商家版订单，非独立商家,或非代理链最底端的独立商家不收费");

			} else {

				if (!isGoodsOwner && !independentMerchant && i != 1) {

					if (Utils.falseIfNull(expectDetailPo
							.getIs_proxy_share_fee_merchant()))
						expectDetailPo.setRemark(null);
					else
						expectDetailPo.setRemark(null);
				}
			}

			if (expectDetailPo.getTotal_foreign_amount().compareTo(
					new BigDecimal("0.01")) == 0) {

				expectDetailPo.setPlatform_fee(BigDecimal.ZERO);
				expectDetailPo.setRemark("渠道商结算金额等于0.01,不收平台费");
			}

			if (foreignCurrency.equalsIgnoreCase(sellerCurrency))
				expectDetailPo.setExchange_rate("1");
			else
				expectDetailPo.setExchange_rate(settleRate.toPlainString());

			if (foreignCurrency.equalsIgnoreCase(sellerCurrency))
				expectDetailPo.setSettlement_amount(foreignAmount.setScale(2, BigDecimal.ROUND_DOWN)
						.subtract(expectDetailPo.getPlatform_fee()).setScale(settlementAmountScale, BigDecimal.ROUND_DOWN));
			else
				expectDetailPo.setSettlement_amount((expectDetailPo
						.getTotal_rmb_amount()
						.multiply(bidVsSettlementExchangeRate)).setScale(2, BigDecimal.ROUND_DOWN)
						.subtract(expectDetailPo.getPlatform_fee()).setScale(settlementAmountScale, BigDecimal.ROUND_DOWN));

			if (whiteGoodsOwnerIdFeeRate != null && goodsOwnerChildId == sellerId) {

				isGoodsOwnerChildIdAmountNotEnough = expectDetailPo.getSettlement_amount().compareTo(BigDecimal.ZERO) < 0;

				if (isGoodsOwnerChildIdAmountNotEnough) {

					if (foreignCurrency.equalsIgnoreCase(sellerCurrency))
						expectDetailPo.setSettlement_amount(foreignAmount);
					else
						expectDetailPo.setSettlement_amount(expectDetailPo
								.getTotal_rmb_amount()
								.multiply(bidVsSettlementExchangeRate)
								.setScale(settlementAmountScale, BigDecimal.ROUND_DOWN));

					expectDetailPo.setRemark(String.format("代理分摊金额渠道大于或等于结算金额,不收平台费, 向上一级parentId:%s收取平台费用, 代理[userId:%s, fee:%s, rate:%s]",
							whiteGoodsOwnerIdOrderSettlementDetail.getUser_id(), goodsOwnerChildId, expectDetailPo.getPlatform_fee(), expectDetailPo.getPlatform_fee_rate().setScale(2, BigDecimal.ROUND_DOWN)));

					// 如果费率分摊的下级用户没有足够的结算金额可以分摊，则需要修改白名单用户的结算金额、费率、平台手续费
					whiteGoodsOwnerIdOrderSettlementDetail.setPlatform_fee_rate(whiteGoodsOwnerIdFeeRate);
					whiteGoodsOwnerIdOrderSettlementDetail.setPlatform_fee(realOrderPaymentDetailAmount
							.multiply(whiteGoodsOwnerIdOrderSettlementDetail.getBid_vs_settlement_exchange_rate())
							.multiply(whiteGoodsOwnerIdOrderSettlementDetail.getPlatform_fee_rate())
							.multiply(new BigDecimal("0.01")).setScale(settlementAmountScale,
									BigDecimal.ROUND_UP));

					if (whiteGoodsOwnerIdOrderSettlementDetail.getForeign_currency().equalsIgnoreCase(whiteGoodsOwnerIdOrderSettlementDetail.getSettlement_currency()))
						whiteGoodsOwnerIdOrderSettlementDetail.setSettlement_amount(whiteGoodsOwnerIdOrderSettlementDetail.getTotal_foreign_amount()
								.subtract(whiteGoodsOwnerIdOrderSettlementDetail.getPlatform_fee()));
					else
						whiteGoodsOwnerIdOrderSettlementDetail.setSettlement_amount(whiteGoodsOwnerIdOrderSettlementDetail
								.getTotal_rmb_amount()
								.multiply(whiteGoodsOwnerIdOrderSettlementDetail.getBid_vs_settlement_exchange_rate()).setScale(2, BigDecimal.ROUND_DOWN)
								.subtract(whiteGoodsOwnerIdOrderSettlementDetail.getPlatform_fee()).setScale(settlementAmountScale, BigDecimal.ROUND_DOWN));

					whiteGoodsOwnerIdOrderSettlementDetail.setRemark(String.format("渠道商费率:%s,代理商费率:%s,代理商费率比例值:%s,childSellerId:%s," +
							"代理分摊失败, 需要独自承担。代理[userId:%s, fee:%s, rate:%s]",
							whiteGoodsOwnerIdFeeRate, goodsOwnerChildFeeRate.setScale(3, BigDecimal.ROUND_HALF_UP), agentRate, goodsOwnerChildId,
							goodsOwnerChildId, expectDetailPo.getPlatform_fee(), expectDetailPo.getPlatform_fee_rate().setScale(2, BigDecimal.ROUND_DOWN)));

					expectDetailPo.setPlatform_fee_rate(BigDecimal.ZERO);
					expectDetailPo.setPlatform_fee(BigDecimal.ZERO);
				}
			}
			
			HashMap<String, BigDecimal> goodsOwnerToChildPriceMap = new HashMap<>();

			if (isPlatformSupplierOrder) {
				
				if (isGoodsOwner) {
					
					BigDecimal totalBidPrice = BigDecimal.ZERO;

					for (OrderDetailPo orderDetailPo : orderDetailList) {
						
						String catalogId = orderDetailPo.getCatalogId();
						Integer productNum = orderDetailPo.getProductCount();
						
						PlatformProductDetail expectPlatformProductDetail = new PlatformProductDetail();
						
						ShenqiProxyChainPo shenqiProxyChainPo = wapper
								.selectProxyChainbyOrderIdAndCatalogIdAndSellerId(
										orderPo.getOrderId(),
										catalogId,
										orderPo.getGoodsOwnerId());
						
						BigDecimal toChildPrice = shenqiProxyChainPo
								.getToChildPrice();
						
						totalBidPrice = toChildPrice.multiply(
								new BigDecimal(productNum)).add(totalBidPrice);
						
						expectPlatformProductDetail.setCatalog_id(catalogId);
						expectPlatformProductDetail.setPlatform_id(orderPo.getGoodsOwnerId());
						expectPlatformProductDetail.setBid_currency(bidCurrency);
						expectPlatformProductDetail.setOrder_id(orderPo.getOrderId());
						expectPlatformProductDetail.setProduct_id(orderDetailPo.getProductId());
						expectPlatformProductDetail.setProduct_num(productNum);
						expectPlatformProductDetail.setProduct_price(toChildPrice);
						expectPlatformProductDetail.setSettlement_currency(sellerCurrency);
						
						platformProductDetailList.add(expectPlatformProductDetail);
						
						goodsOwnerToChildPriceMap.put(catalogId, toChildPrice);
					}
					
					BigDecimal feeRate = this.getPlatformFeeRateNew(
							expectDetailPo.getPay_channel_type(),
							orderPo.getGoodsOwnerId(), false,
							chargeIndependentMerchant,
							true, platformProductDetailList, payMode, orderType);
					
					expectDetailPo.setPlatform_fee_rate(feeRate);
					
					platformFee = totalBidPrice
							.multiply(bidVsSettlementExchangeRate)
							.multiply(feeRate).multiply(new BigDecimal("0.01"));
					
					expectDetailPo.setPlatform_fee(platformFee.setScale(2, BigDecimal.ROUND_UP));
					
					platformProductDetailList.forEach(detailPo -> {

						detailPo.setPlatform_rate(feeRate);
					});
					
					expectDetailPo.setSettlement_amount(expectDetailPo
							.getTotal_foreign_amount()
							.subtract(expectDetailPo.getPlatform_fee()));
					
					expectDetailPo.setRemark("平台供货商订单, 货头收取平台供货商手续费.");
				}
			}

			if (Utils.emptyIfNull(paymentPo.getAppName()).equalsIgnoreCase(orderPo.getSellerId().toString()) ||
					Utils.emptyIfNull(paymentPo.getAppName()).equalsIgnoreCase("500024716"))
				expectDetailPo.setIs_personal_applet(true);
			else
				expectDetailPo.setIs_personal_applet(false);

			expectDetailPo.setOrder_foreign_amount(realOrderForeignAmount
					.setScale(foreignAmountScale, BigDecimal.ROUND_DOWN));
			expectDetailPo.setPayment_id(paymentDetailPo.getPaymentId());

			expectDetailPo
					.setBid_vs_settlement_exchange_rate(bidVsSettlementExchangeRate
							.setScale(6, BigDecimal.ROUND_HALF_DOWN));
			expectDetailPo.setBiz_id(String.valueOf(orderPo.getOrderId()));
			expectDetailPo.setSettlement_type(0);
			
			expectDetailPo.setFund_not_collect_merchant_id(isPlatformSupplierOrder ? null : fundNotCollectMerchantId);
			expectDetailPo.setSettlement_way(0);
			expectDetailPo.setIs_platform_supplier(isPlatformSupplierOrder);

			BigDecimal settlementAmount = expectDetailPo.getSettlement_amount();

			if (isRefunded) {
				Logger.comment("验证代理订单的退货退款结算单");

				for (Map.Entry<RefundBillPo, HashMap<Long, BigDecimal>> entry : refundBillWithRefundedProfitMap
						.entrySet()) {

					if (expectDetailPo.getSettlement_status() != 2)
						this.verifyRefundedOrderSettlementDetail(
								entry.getKey(), actualDetailPo, orderPo,
								entry.getValue(), orderDetailList, goodsOwnerToChildPriceMap);

					if (isRefundedFailed) {

						if (expectDetailPo.getSettlement_status() == 2) {

							// 结算表有多条用户的结算数据，根据actualList的大小判断
							this.verifyRefundedFailedOrderSettlementDetail(
									actualDetailPo, String
											.valueOf(expectDetailPo
													.getOrder_id()), actualList
											.size());
						} else {

							String refundBillNo = entry.getKey()
									.getRefundBillNo();

							// 结算表有多条用户的结算数据，根据actualList的大小判断
							this.verifyRefundedFailedOrderSettlementDetail(
									actualDetailPo, refundBillNo,
									actualList.size());
						}
					}
				}
			}

			// 如果结算金额小于0并且是期望是结算状态，先查询渠道商是否有足够的账户金额
			if (settlementAmount.compareTo(BigDecimal.ZERO) == -1 && settled)
				negativeProfitUnableSettle = getNegativeProfitUnableSettle(actualDetailPo);

			if (actualDetailPo.getUser_role()
					.compareToIgnoreCase("GOODS_OWNER") == 0)
				this.verifyProviderSettlementDetail(actualDetailPo, false,
						independentMerchant, isShengPay, isRefunded, false, isRefundedFailed);

			// 如果是货头，判断是否开启了分销裂变功能
			if (isGoodsOwner) {

				proxyFissionConfig = proxyFissionConfigWrapper
						.selectLatestByMerchantId(actualDetailPo
								.getGoods_owner_id());
				if (null != proxyFissionConfig) {

					isProxyFission = true;
					proxyFissionSellerId = orderPo.getSellerId();
				}
			}	
			
			if (chargeIndependentMerchant)
				chargeIndependentMerchantOrderSettlementDetail = actualDetailPo;

			actualList.add(actualDetailPo);
			expectList.add(expectDetailPo);
		}

		if (negativeProfitUnableSettle) {

			for (OrderSettlementDetail orderSettlementDetail : expectList)
				orderSettlementDetail.setSettlement_status(0);
		}

		for (int i = 0; i < actualList.size(); i++) {
			Logger.comment("验证结算单");
			
			Boolean isGoodsOwnerOrderSettlementDetail = actualList.get(i)
					.getUser_role().equalsIgnoreCase("GOODS_OWNER");

			// 货头结算单
			if (isGoodsOwnerOrderSettlementDetail) {

				// 如果是独立商家的供货商，且为线下结算时，需要修改数据
				if (isIndependentOrder && goodsOwnerSettlementConfig != null) {
					if (goodsOwnerSettlementConfig.getSettlement_way() == 1) {

						OrderSettlementDetail goodsOwnerOrderSettlementDetail = expectList
								.get(i);
						int settlementPeriodType = goodsOwnerSettlementConfig
								.getSettlement_period_type();

						goodsOwnerOrderSettlementDetail
								.setGoods_owner_settlement_config_id(goodsOwnerSettlementConfig
										.getId());

						if (null != actualList.get(i).getDelivered_time()
								&& settlementPeriodType == 1) {

							int delayDays = goodsOwnerSettlementConfig
									.getSettlement_period_day();

							goodsOwnerOrderSettlementDetail
									.setGoods_owner_settlement_expected_time(YMTDateUtil
											.getBeforeOrNextDate(
													actualList
															.get(i)
															.getDelivered_time(),
													delayDays));

							if (isCollectingForOthersSettled) {

								String expectTimeDateString = YMTDateUtil
										.getBeforeOrNextDay(-1,
												YMTDateUtil.YMDHMS);

								// 修改供货商的预期结算时间
								orderSettlementDetailWrapper
										.updateGoodsOwnerSettlementExpectedTimeByOrderIdAndUserId(
												goodsOwnerOrderSettlementDetail
														.getOrder_id(),
												goodsOwnerOrderSettlementDetail
														.getUser_id(),
												expectTimeDateString);

								// 供货商线下结算
								ShenqiSettlementService
										.doGoodsOwnerOfflineSettlement();

								goodsOwnerOrderSettlementDetail
										.setSettlement_status(1);
							} else {

								goodsOwnerOrderSettlementDetail
										.setSettlement_status(0);
							}
						} else
							goodsOwnerOrderSettlementDetail
									.setGoods_owner_settlement_expected_time(null);

						goodsOwnerOrderSettlementDetail
								.setGoods_owner_settlement_period_type(settlementPeriodType);
						goodsOwnerOrderSettlementDetail
								.setDependent_merchant_id(chargeIndependentMerchantId);
						goodsOwnerOrderSettlementDetail
								.setSettlement_way(goodsOwnerSettlementConfig
										.getSettlement_way());
						goodsOwnerOrderSettlementDetail.setSettlement_status(0);

						this.verifyCollectingForOthersOrderSettlementDetail(
								chargeIndependentMerchantOrderSettlementDetail,
								goodsOwnerOrderSettlementDetail, isRefunded,
								refundBillWithRefundedProfitMap,
								isRefundedFailed);
					}
				}

				// 校验分销裂变的OrderSettlementDetail
				if (isProxyFission)
					this.verifyPromotersOrderSettlementDetail(
							actualList.get(i), proxyFissionConfig,
							orderPo.getUserId(), orderDetailList,
							orderPo.getPayableAmount(), proxyFissionSellerId,
							isRefunded, refundBillWithRefundedProfitMap, orderPo.getShenqiProxyBuyOrder());

				// 如果是平台供货商订单，校验platform_product_detail
				if (isPlatformSupplierOrder)
					this.verifyPlatformProductDetail(orderPo.getOrderId(),
							platformProductDetailList);
			}
			
			ShenqiSettlementVerifyTableService
					.verifyOrderSettlementDetailTable(expectList.get(i),
							actualList.get(i));
		}
	}

	public void verifyRefundedOrderSettlementDetail(RefundBillPo refundBillPo,
			OrderSettlementDetail orderSettlementDetail, OrderPo orderPo,
			HashMap<Long, BigDecimal> refundedProfitMap,
			List<OrderDetailPo> orderDetailList,
			HashMap<String, BigDecimal> goodsOwnerToChildPriceMap)
			throws CloneNotSupportedException {

		if (orderSettlementDetail.getTotal_rmb_amount().compareTo(
				BigDecimal.ZERO) == 0) {
			Logger.comment("收入结算单结算金额为0，不生成退款结算单，id: "
					+ orderSettlementDetail.getId() + ", orderId: "
					+ orderSettlementDetail.getOrder_id());

			return;
		}

		String bizId = refundBillPo.getRefundBillNo();

		OrderSettlementDetail actualDetailPo = orderSettlementDetailWrapper
				.selectRefundedByOrderIdAndUserId(
						orderSettlementDetail.getOrder_id(),
						orderSettlementDetail.getUser_id(), bizId);
		OrderSettlementDetail exepectDetailPo = (OrderSettlementDetail) orderSettlementDetail
				.clone();

		BigDecimal refundedAmount = refundedProfitMap.get(
				orderSettlementDetail.getUser_id()).negate();
		BigDecimal refundedTotalForeignAmount = refundedAmount
				.multiply(orderSettlementDetail.getTotal_foreign_amount())
				.divide(orderSettlementDetail.getTotal_rmb_amount(), 6, BigDecimal.ROUND_HALF_UP);

		refundedTotalForeignAmount = refundedTotalForeignAmount.setScale(2,
				BigDecimal.ROUND_DOWN);

		exepectDetailPo.setTotal_foreign_amount(refundedTotalForeignAmount);

		BigDecimal refunedSettlementAmount = refundedAmount
				.multiply(orderSettlementDetail
						.getBid_vs_settlement_exchange_rate());
		
		BigDecimal refundedPlatformFee;

		if (Utils.falseIfNull(orderSettlementDetail.getIs_platform_supplier())
				&& orderSettlementDetail.getUser_role().equalsIgnoreCase(
						"GOODS_OWNER")) {
			
			BigDecimal toChildPrice = goodsOwnerToChildPriceMap.get(refundBillPo.getCatalogId());
			
			// 如果是平台供货商的货头，则手续费根据退款数量退款 
			refundedPlatformFee = toChildPrice
					.multiply(new BigDecimal(refundBillPo.getProductCount()))
					.multiply(orderSettlementDetail.getPlatform_fee_rate())
					.multiply(
							orderSettlementDetail
									.getBid_vs_settlement_exchange_rate())
					.divide(new BigDecimal("100.00"))
					.setScale(this.getScale(orderSettlementDetail.getSettlement_currency()), BigDecimal.ROUND_DOWN);
		} else {

			refundedPlatformFee = orderSettlementDetail
					.getPlatform_fee()
					.multiply(refundedAmount)
					.divide(orderSettlementDetail.getTotal_rmb_amount(), 6,
							BigDecimal.ROUND_HALF_UP)
					.setScale(this.getScale(orderSettlementDetail.getSettlement_currency()), BigDecimal.ROUND_DOWN);
		}
		
		if (refunedSettlementAmount.compareTo(BigDecimal.ZERO) == -1)
			refunedSettlementAmount = refunedSettlementAmount.setScale(2,
					BigDecimal.ROUND_UP);
		else
			refunedSettlementAmount = refunedSettlementAmount.setScale(2,
					BigDecimal.ROUND_DOWN);

		exepectDetailPo.setBiz_id(bizId);
		exepectDetailPo.setSettlement_type(1);
		exepectDetailPo.setTotal_rmb_amount(refundedAmount);

		exepectDetailPo.setSettlement_amount((refunedSettlementAmount
				.subtract(refundedPlatformFee)).abs().min(
				actualDetailPo.getSettlement_amount()));
		exepectDetailPo.setPlatform_fee(refundedPlatformFee.abs());
		exepectDetailPo.setRemark(null);

		ShenqiSettlementVerifyTableService.verifyOrderSettlementDetailTable(
				exepectDetailPo, actualDetailPo);
	}

	public void verifyRefundedFailedOrderSettlementDetail(
			OrderSettlementDetail orderSettlementDetail, String refundBillNo,
			int count) throws CloneNotSupportedException, InterruptedException {

		Logger.comment("验证退款失败结算单");

		Long userId = orderSettlementDetail.getUser_id();
		Long orderId = orderSettlementDetail.getOrder_id();

		if (count == 0) {

			// 执行该回调，生成退款失败结算单
			SqTradingCallService.onRefundFailEvent(orderId, refundBillNo);

			// 执行该job，结算退款失败结算单
			ShenqiSettlementService.executeRefundFailSettlementTask();
		}

		OrderSettlementDetail refundedDetailPo = orderSettlementDetailWrapper
				.selectRefundedByOrderIdAndUserId(orderId, userId, refundBillNo);

		OrderSettlementDetail expectDetailPo = (OrderSettlementDetail) refundedDetailPo
				.clone();

		OrderSettlementDetail actualDetailPo = orderSettlementDetailWrapper
				.selectRefundFailedByOrderIdAndUserId(orderId, userId,
						refundBillNo);

		if (orderSettlementDetail.getSettlement_status() == 0
				&& orderSettlementDetail.getSettlement_way() == 0) {

			Logger.comment("主结算单还在结算中,无法生成退款失败结算单");

			Logger.verifyEquals(null, actualDetailPo, "主结算单还在结算中,无法生成退款失败结算单");

			return;
		}

		expectDetailPo.setSettlement_type(4);

		if (orderSettlementDetail.getSettlement_status() == 2) {

			expectDetailPo.setTotal_rmb_amount(refundedDetailPo
					.getTotal_rmb_amount());
			expectDetailPo.setSettlement_amount(refundedDetailPo
					.getSettlement_amount());
			expectDetailPo.setTotal_foreign_amount(refundedDetailPo
					.getTotal_foreign_amount());
			expectDetailPo.setSettlement_status(1);
			expectDetailPo.setIs_rollback(false);
		} else {

			expectDetailPo.setTotal_rmb_amount(refundedDetailPo
					.getTotal_rmb_amount().negate());
			expectDetailPo.setSettlement_amount(refundedDetailPo
					.getSettlement_amount().negate());
			expectDetailPo.setTotal_foreign_amount(refundedDetailPo
					.getTotal_foreign_amount().negate());
		}

		expectDetailPo.setSettlement_time(YMTDateUtil.getDate());
		expectDetailPo.setRemark(null);

		ShenqiSettlementVerifyTableService.verifyOrderSettlementDetailTable(
				expectDetailPo, actualDetailPo);
	}

	public void verifyPromotersOrderSettlementDetail(
			OrderSettlementDetail orderSettlementDetail,
			ProxyFissionConfig proxyFissionConfig,
			Long userId,
			List<OrderDetailPo> orderDetailPoList,
			BigDecimal orderBidRealPayAmount,
			Long proxyFissionSellerId,
			Boolean isRefunded,
			HashMap<RefundBillPo, HashMap<Long, BigDecimal>> refundBillWithRefundedProfitMap,
			Boolean isShenqiProxyBuyOrder)
			throws Exception {

		long orderId = orderSettlementDetail.getOrder_id();

		HashMap<String, List<AgentPromoterRelationSettlementBean>> agentPromoterRelationMap = ProxyFissionVerifyService
				.buildAgentPromoterRelation(orderSettlementDetail,
						proxyFissionConfig, orderDetailPoList, userId,
						orderBidRealPayAmount, proxyFissionSellerId,
						isRefunded, refundBillWithRefundedProfitMap, isShenqiProxyBuyOrder);

		List<AgentPromoterRelationSettlementBean> agentPromoterRelationSettlementBeanList = agentPromoterRelationMap
				.get("settlement");
		List<AgentPromoterRelationSettlementBean> refundAgentPromoterRelationSettlementBeanList = agentPromoterRelationMap
				.get("refund");

		for (AgentPromoterRelationSettlementBean agentPromoterRelationSettlementBean : agentPromoterRelationSettlementBeanList) {

			Long fissionProxyId = agentPromoterRelationSettlementBean
					.getInviterId();
			String bizId = agentPromoterRelationSettlementBean
					.getBizId() + "-" + fissionProxyId;

			// 5：从货头收益中扣除代理佣金，6：返还从代理佣金给货头
			OrderSettlementDetail actualDetailPo = orderSettlementDetailWrapper
					.selectPromotersDetailByOrderIdAndUserIdAndProxyFissonId(
							orderId, orderSettlementDetail.getUser_id(),
							fissionProxyId, 5, bizId);

			OrderSettlementDetail expectDetailPo = (OrderSettlementDetail) orderSettlementDetail
					.clone();

			BigDecimal totalRmbAmount = agentPromoterRelationSettlementBean
					.getSumBidSettlementAmount().negate();
			BigDecimal settlementAmount = totalRmbAmount.multiply(
					expectDetailPo.getBid_vs_settlement_exchange_rate())
					.setScale(2, BigDecimal.ROUND_DOWN);

			expectDetailPo.setTotal_rmb_amount(totalRmbAmount);
			expectDetailPo.setTotal_foreign_amount(BigDecimal.ZERO);
			expectDetailPo.setPlatform_fee_rate(BigDecimal.ZERO);
			expectDetailPo.setPlatform_fee(BigDecimal.ZERO);
			expectDetailPo.setSettlement_amount(settlementAmount);
			expectDetailPo.setBiz_id(agentPromoterRelationSettlementBean
					.getBizId() + "-" + fissionProxyId);
			expectDetailPo.setFission_proxy_id(fissionProxyId);
			expectDetailPo.setSettlement_type(5);
			expectDetailPo
					.setSettlement_time(agentPromoterRelationSettlementBean
							.getExpectSettlementTime());
			expectDetailPo
					.setSettlement_status(agentPromoterRelationSettlementBean
							.getSettlementStatus());

			ShenqiSettlementVerifyTableService
					.verifyOrderSettlementDetailTable(expectDetailPo,
							actualDetailPo);

			if (orderSettlementDetail.getSettlement_status() == 2
					&& null == orderSettlementDetail.getSettlement_time())
				agentPromoterRelationSettlementBean.setSettlementStatus(4);

			ProxyFissionVerifyService.verifyProxyFissionSettlementDetail(
					orderSettlementDetail, agentPromoterRelationSettlementBean);

			for (AgentPromoterProductBean agentPromoterProductBean : agentPromoterRelationSettlementBean
					.getAgentPromoterProductBeanList()) {
				ProxyFissionVerifyService.verifyProxyFissionProductDetail(
						orderSettlementDetail, agentPromoterProductBean,
						agentPromoterRelationSettlementBean.getLayer());
			}
		}

		if (isRefunded || orderSettlementDetail.getSettlement_status() == 2) {

			for (AgentPromoterRelationSettlementBean agentPromoterRelationSettlementBean : refundAgentPromoterRelationSettlementBeanList) {

				Long fissionProxyId = agentPromoterRelationSettlementBean
						.getInviterId();
				String[] bizIds = agentPromoterRelationSettlementBean
						.getBizId().split("-");

				String bizId = bizIds[0] + "-" + bizIds[1] + "-" + fissionProxyId + "-" + bizIds[2];

				// 5：从货头收益中扣除代理佣金，6：返还从代理佣金给货头
				OrderSettlementDetail actualDetailPo = orderSettlementDetailWrapper
						.selectPromotersDetailByOrderIdAndUserIdAndProxyFissonId(
								orderId, orderSettlementDetail.getUser_id(),
								fissionProxyId, 6, bizId);

				OrderSettlementDetail expectDetailPo = (OrderSettlementDetail) orderSettlementDetail
						.clone();

				BigDecimal totalRmbAmount = agentPromoterRelationSettlementBean
						.getSumBidSettlementAmount().negate();
				BigDecimal settlementAmount = totalRmbAmount.multiply(
						expectDetailPo.getBid_vs_settlement_exchange_rate())
						.setScale(2, BigDecimal.ROUND_HALF_UP);

				expectDetailPo.setTotal_rmb_amount(totalRmbAmount);
				expectDetailPo.setTotal_foreign_amount(BigDecimal.ZERO);
				expectDetailPo.setPlatform_fee_rate(BigDecimal.ZERO);
				expectDetailPo.setPlatform_fee(BigDecimal.ZERO);
				expectDetailPo.setSettlement_amount(settlementAmount);
				expectDetailPo.setBiz_id(bizIds[0] + "-" + bizIds[1] + "-"
						+ fissionProxyId + "-" + bizIds[2]);
				expectDetailPo.setFission_proxy_id(fissionProxyId);
				expectDetailPo.setSettlement_type(6);
				expectDetailPo
						.setSettlement_time(agentPromoterRelationSettlementBean
								.getExpectSettlementTime());
				expectDetailPo
						.setSettlement_status(agentPromoterRelationSettlementBean
								.getSettlementStatus());

				ShenqiSettlementVerifyTableService
						.verifyOrderSettlementDetailTable(expectDetailPo,
								actualDetailPo);

				ProxyFissionVerifyService.verifyProxyFissionSettlementDetail(
						orderSettlementDetail,
						agentPromoterRelationSettlementBean);
			}
		}
	}

	public void verifyCollectingForOthersOrderSettlementDetail(
			OrderSettlementDetail chargeIndependentMerchantOrderSettlementDetail,
			OrderSettlementDetail goodsOwnerOrderSettlementDetail,
			Boolean isRefunded,
			HashMap<RefundBillPo, HashMap<Long, BigDecimal>> refundBillWithRefundedProfitMap, 
			Boolean isRefundedFailed)
			throws CloneNotSupportedException {

		long orderId = chargeIndependentMerchantOrderSettlementDetail
				.getOrder_id();
		long userId = chargeIndependentMerchantOrderSettlementDetail
				.getUser_id();

		OrderSettlementDetail expectDetailPo = (OrderSettlementDetail) chargeIndependentMerchantOrderSettlementDetail
				.clone();

		OrderSettlementDetail actualDetailPo = orderSettlementDetailWrapper
				.selectCollectingForOthersByOrderIdAndUserId(orderId, userId);
		
		BigDecimal totalRmbAmount = goodsOwnerOrderSettlementDetail.getTotal_rmb_amount();
		BigDecimal totalForeignAmount = goodsOwnerOrderSettlementDetail.getTotal_foreign_amount();

		expectDetailPo.setTotal_rmb_amount(totalRmbAmount);
		expectDetailPo.setTotal_foreign_amount(totalForeignAmount);
		expectDetailPo.setPlatform_fee_rate(BigDecimal.ZERO);
		expectDetailPo.setPlatform_fee(BigDecimal.ZERO);
		expectDetailPo.setSettlement_amount(totalForeignAmount);
		expectDetailPo.setRemark("代收货款结算单不收手续费");
		expectDetailPo.setSettlement_type(9);
		expectDetailPo.setParent_proxy_id(null);
		
		ShenqiSettlementVerifyTableService.verifyOrderSettlementDetailTable(
				expectDetailPo, actualDetailPo);
		
		if (isRefunded) {
			Logger.comment("验证代收货款的退货退款结算单");

			for (Map.Entry<RefundBillPo, HashMap<Long, BigDecimal>> entry : refundBillWithRefundedProfitMap
					.entrySet()) {

				if (expectDetailPo.getSettlement_status() != 2) {

					String refundBillNo = entry.getKey().getRefundBillNo();

					OrderSettlementDetail refundedGoodsOwnerOrderSettlementDetail = orderSettlementDetailWrapper
							.selectRefundedByOrderIdAndUserId(orderId,
									goodsOwnerOrderSettlementDetail
											.getUser_id(), refundBillNo);

					expectDetailPo
							.setTotal_foreign_amount(refundedGoodsOwnerOrderSettlementDetail
									.getTotal_foreign_amount());
					expectDetailPo
							.setTotal_rmb_amount(refundedGoodsOwnerOrderSettlementDetail
									.getTotal_rmb_amount());
					expectDetailPo
							.setSettlement_amount(refundedGoodsOwnerOrderSettlementDetail
									.getSettlement_amount());
					expectDetailPo.setRemark(null);
					expectDetailPo.setSettlement_type(10);
					expectDetailPo.setBiz_id(refundBillNo);

					OrderSettlementDetail actualRefundedDetailPo = orderSettlementDetailWrapper
							.selectRefundedCollectingForOthersByOrderIdAndUserId(
									orderId, userId, refundBillNo);

					ShenqiSettlementVerifyTableService
							.verifyOrderSettlementDetailTable(expectDetailPo,
									actualRefundedDetailPo);
					
					if (isRefundedFailed) {

						expectDetailPo.setTotal_foreign_amount(expectDetailPo
								.getTotal_foreign_amount().negate());
						expectDetailPo.setTotal_rmb_amount(expectDetailPo
								.getTotal_rmb_amount().negate());
						expectDetailPo.setSettlement_amount(expectDetailPo
								.getSettlement_amount().negate());
						expectDetailPo.setSettlement_type(11);
						
						OrderSettlementDetail actualRefundedFailedDetailPo = orderSettlementDetailWrapper
								.selectRefundedFailedCollectingForOthersByOrderIdAndUserId(
										orderId, userId, refundBillNo);
						
						ShenqiSettlementVerifyTableService
								.verifyOrderSettlementDetailTable(
										expectDetailPo, actualRefundedFailedDetailPo);
					}
				}
			}
		}
	}
	
	public void verifyRefundedCollectingForOthersOrderSettlementDetail(
			OrderSettlementDetail chargeIndependentMerchantOrderSettlementDetail,
			OrderSettlementDetail goodsOwnerOrderSettlementDetail)
			throws CloneNotSupportedException {

		long orderId = chargeIndependentMerchantOrderSettlementDetail
				.getOrder_id();
		long userId = chargeIndependentMerchantOrderSettlementDetail
				.getUser_id();

		OrderSettlementDetail expectDetailPo = (OrderSettlementDetail) chargeIndependentMerchantOrderSettlementDetail
				.clone();

		OrderSettlementDetail actualDetailPo = orderSettlementDetailWrapper
				.selectCollectingForOthersByOrderIdAndUserId(orderId, userId);
		
		BigDecimal totalRmbAmount = goodsOwnerOrderSettlementDetail.getTotal_rmb_amount();
		BigDecimal totalForeignAmount = goodsOwnerOrderSettlementDetail.getTotal_foreign_amount();

		expectDetailPo.setTotal_rmb_amount(totalRmbAmount);
		expectDetailPo.setTotal_foreign_amount(totalForeignAmount);
		expectDetailPo.setPlatform_fee_rate(BigDecimal.ZERO);
		expectDetailPo.setPlatform_fee(BigDecimal.ZERO);
		expectDetailPo.setSettlement_amount(totalForeignAmount);
		expectDetailPo.setRemark("代收货款结算单不收手续费");
		expectDetailPo.setSettlement_type(9);
		expectDetailPo.setParent_proxy_id(null);
		
		ShenqiSettlementVerifyTableService.verifyOrderSettlementDetailTable(
				expectDetailPo, actualDetailPo);
	}
	
	public void verifyPlatformProductDetail(Long orderId, List<PlatformProductDetail> platformProductDetailList) {
		
		PlatformProductDetailWrapper platformProductDetailWrapper = new PlatformProductDetailWrapper();
		
		List<PlatformProductDetail> actualPlatformProductDetailList = platformProductDetailWrapper.selectByOrderId(orderId);
		
		Logger.verifyEquals(platformProductDetailList.size(), actualPlatformProductDetailList.size(), "验证platform_product_detail数据size");
		
		for (PlatformProductDetail expectPlatformProductDetail : platformProductDetailList) {
		
			String catalogId = expectPlatformProductDetail.getCatalog_id();
			
			PlatformProductDetail actualPlatformProductDetail = actualPlatformProductDetailList
					.stream()
					.filter(expect -> expect.getCatalog_id().equalsIgnoreCase(
							catalogId)).collect(Collectors.toList()).get(0);
			
			ShenqiSettlementVerifyTableService.verifyPlatformProductDetailTable(
					expectPlatformProductDetail, actualPlatformProductDetail);
		}
	}
	
	private boolean getNegativeProfitUnableSettle(
			OrderSettlementDetail orderSettlementDetail)
			throws InterruptedException {

		if (null == orderSettlementDetail)
			return false;

		AccountWapper accountWapper = new AccountWapper();

		int accountType = getAccountType(0,
				orderSettlementDetail.getSettlement_currency(),
				Utils.zeroIfNull(orderSettlementDetail
						.getFund_not_collect_merchant_id()) > 0 );

		List<AccountEntry> entryList = accountWapper.selectAccountEntry(
				orderSettlementDetail.getUser_id().intValue(),
				String.valueOf(orderSettlementDetail.getOrder_id()),
				accountType);

		// 如果账户中的余额小于结算金额，则无法进行结算
		if (entryList.size() == 0)
			return true;
		else if (entryList.get(0).getAmount()
				.compareTo(orderSettlementDetail.getSettlement_amount()) == 0)
			return false;
		else
			return true;
	}

	public String convertSpecialCurrency(String specialCurrency) {

		// 如果买手的币种为特殊币种，则结算币种为USD
		if (specialCurrency.equalsIgnoreCase("KRW") || specialCurrency.equalsIgnoreCase("CHF") || specialCurrency.equalsIgnoreCase("NZD")
				|| specialCurrency.equalsIgnoreCase("AUD"))
			return "USD";
		else
			return specialCurrency;
	}
	
	public static void main(String[] args) {
		System.out.println(2141);
	}
}
